英文:
UWP Custom UI Element Render Bug
问题
我已经创建了一个自定义类,它继承自Path
类(用于绘制箭头头部)在UWP中,现在看起来它工作正常,但当我尝试将两个这些元素放在屏幕上时,一个不会渲染。我初始化的第一个元素将会被渲染,我认为这可能与类实例引用彼此之间共享的某些指针有关,但我还没有找到解决办法。
以下是我编写的自定义类的代码:
public sealed partial class TimePickerArrow : Path
{
#region Arrow Direction XAML Property
public enum Directions
{
Up = 0,
Down = 180,
Left = -90,
Right = 90
};
public static readonly DependencyProperty DirectionProperty =
DependencyProperty.Register("Direction", typeof(Directions), typeof(TimePickerArrow), new PropertyMetadata(Directions.Up, OnArrowDirectionChanged));
public Directions Direction
{
get { return (Directions)GetValue(DirectionProperty); }
set { SetValue(DirectionProperty, value); }
}
#endregion
#region Arrow Hover Effect Fill Xaml Property
public static readonly DependencyProperty HoverFillProperty =
DependencyProperty.Register("HoverFill", typeof(Brush), typeof(TimePickerArrow), new PropertyMetadata(new SolidColorBrush(Colors.Gray)));
public Brush HoverFill
{
get { return (Brush)GetValue(HoverFillProperty); }
set { SetValue(HoverFillProperty, value); }
}
#endregion
// 静态箭头颜色由路径的填充属性设置,
// 用于保存悬停时更改的原始箭头填充颜色
Brush StaticFill;
public TimePickerArrow()
{
#region PATH PROPERTIES INIT
this.Direction = Direction;
this.HoverFill = HoverFill;
this.Fill = new SolidColorBrush(Colors.Black);
this.StaticFill = Fill;
#endregion
InitArrowPath();
this.PointerEntered += TimePickerArrow_HoverEntered;
this.PointerExited += TimePickerArrow_HoverExited;
}
private void InitArrowPath()
{
this.Style = Application.Current.Resources["TimePickerArrowPath"] as Style;
}
private static void OnArrowDirectionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TimePickerArrow arrow = (TimePickerArrow)d;
Directions newArrowDirection = (Directions)e.NewValue;
// 根据新的Direction值更新RenderTransform
CompositeTransform arrowDirectionRotation = new CompositeTransform();
arrowDirectionRotation.Rotation = (double)newArrowDirection;
arrow.RenderTransform = arrowDirectionRotation;
}
private void TimePickerArrow_HoverEntered(object sender, PointerRoutedEventArgs e)
{
this.Fill = HoverFill;
}
private void TimePickerArrow_HoverExited(object sender, PointerRoutedEventArgs e)
{
this.Fill = StaticFill;
}
}
以下是在InitPath()方法中引用的样式:
<Style x:Key="TimePickerArrowPath" TargetType="Path">
<Setter Property="Data" Value="M32 6 L58 32 L48.07142857142857 41.92857142857143 L32 25.857142857142854 L16 41.92857142857143 L6 31.92857142857143 Z"/>
<Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
<Setter Property="Stretch" Value="Fill"/>
</Style>
感谢任何选择贡献的人。
英文:
I've created a custom class for an Element that inherits from Path
class (An Arrow Head drawing) in UWP now it seems to be working fine but when I try to put 2 of those elements on the screen one doesn't render. The one I initialized first is the one that is going to be rendered I though it might have something to do with the class instances referencing some pointers that are shared between them or something of that sort but I yet to have found a solution.
Now here is the code for the custom class I wrote:
public sealed partial class TimePickerArrow : Path
{
#region Arrow Direction XAML Property
public enum Directions
{
Up = 0,
Down = 180,
Left = -90,
Right = 90
};
public static readonly DependencyProperty DirectionProperty =
DependencyProperty.Register("Direction", typeof(Directions), typeof(TimePickerArrow), new PropertyMetadata(Directions.Up, OnArrowDirectionChanged));
public Directions Direction
{
get { return (Directions)GetValue(DirectionProperty); }
set { SetValue(DirectionProperty, value); }
}
#endregion
#region Arrow Hover Effect Fill Xaml Property
public static readonly DependencyProperty HoverFillProperty =
DependencyProperty.Register("HoverFill", typeof(Brush), typeof(TimePickerArrow), new PropertyMetadata(new SolidColorBrush(Colors.Gray)));
public Brush HoverFill
{
get { return (Brush)GetValue(HoverFillProperty); }
set { SetValue(HoverFillProperty, value); }
}
#endregion
// static arrow color set by the Fill property of the path,
// used to save the original arrow fill color that gets changed on hover
Brush StaticFill;
public TimePickerArrow()
{
#region PATH PROPERTIES INIT
this.Direction = Direction;
this.HoverFill = HoverFill;
this.Fill = new SolidColorBrush(Colors.Black);
this.StaticFill = Fill;
#endregion
InitArrowPath();
this.PointerEntered += TimePickerArrow_HoverEntered;
this.PointerExited += TimePickerArrow_HoverExited;
}
private void InitArrowPath()
{
this.Style = Application.Current.Resources["TimePickerArrowPath"] as Style;
}
private static void OnArrowDirectionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TimePickerArrow arrow = (TimePickerArrow)d;
Directions newArrowDirection = (Directions)e.NewValue;
// Update the RenderTransform based on the new Direction value
CompositeTransform arrowDirectionRotation = new CompositeTransform();
arrowDirectionRotation.Rotation = (double)newArrowDirection;
arrow.RenderTransform = arrowDirectionRotation;
}
private void TimePickerArrow_HoverEntered(object sender, PointerRoutedEventArgs e)
{
this.Fill = HoverFill;
}
private void TimePickerArrow_HoverExited(object sender, PointerRoutedEventArgs e)
{
this.Fill = StaticFill;
}
}
And here is the style referenced in InitPath() method:
<Style x:Key="TimePickerArrowPath" TargetType="Path">
<Setter Property="Data" Value="M32 6 L58 32 L48.07142857142857 41.92857142857143 L32 25.857142857142854 L16 41.92857142857143 L6 31.92857142857143 Z"/>
<Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
<Setter Property="Stretch" Value="Fill"/>
</Style>
Thanks to anybody who chooses to contribute.
答案1
得分: 0
我无法相信我在这上面浪费了这么多时间,问题出在这一行:
this.Style = Application.Current.Resources["TimePickerArrowPath"] as Style;
因为它是整个应用程序的静态全局资源,因此在所有实例之间共享,这是它们唯一共享的东西,这解释了为什么只有第一个初始化的实例被绘制到屏幕上,因为它是第一个“获取到”样式资源的实例,我尝试了改变形状并删除样式,这就是我看到的,也是我想明白的地方。
我通过在代码中为每个实例创建一个新的样式来解决了这个问题,像这样:
Style arrowStyle = new Style(typeof(Path));
arrowStyle.Setters.Add(new Setter(Path.DataProperty, "M32 6 L58 32 L48.07142857142857 41.92857142857143 L32 25.857142857142854 L16 41.92857142857143 L6 31.92857142857143 Z"));
arrowStyle.Setters.Add(new Setter(Path.RenderTransformOriginProperty, new Point(0.5, 0.5)));
arrowStyle.Setters.Add(new Setter(Path.StretchProperty, Stretch.Fill));
this.Style = arrowStyle;
P.S: 有趣的是,我只需要样式来初始化 Path.Data 属性,而不是干扰 XAML Geometry。
英文:
I can't believe I wasted so much time on this, the problem layed down in this line:
this.Style = Application.Current.Resources["TimePickerArrowPath"] as Style;
Since it's a static global resource for the whole Application it's shared amongst all instances and its the only thign they share, expalining only the first initalized being drawn to the screen since its the first one to "get hold" of the style resource, I just tried to change the shape and removed the style and that's where I saw and it hit me.
I was able to solve the problem by creating a new Style each instance in the code like that
Style arrowStyle = new Style(typeof(Path));
arrowStyle.Setters.Add(new Setter(Path.DataProperty, "M32 6 L58 32 L48.07142857142857 41.92857142857143 L32 25.857142857142854 L16 41.92857142857143 L6 31.92857142857143 Z"));
arrowStyle.Setters.Add(new Setter(Path.RenderTransformOriginProperty, new Point(0.5, 0.5)));
arrowStyle.Setters.Add(new Setter(Path.StretchProperty, Stretch.Fill));
this.Style = arrowStyle;
P.S: Funny but I needed the style only for the purpose of initalizing the Path.Data property with a string and not messing with XAML Geometry
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论