我在C#-WPF工作。
我制作了自己的UserControl,这是一个简单的交叉。使用坐标,我可以在图像上绘制X.
参数是:
我的Cross.xaml:
<UserControl x:Name="userControl"
x:Class="Project.Cross">
<Grid>
<Line Stroke="{Binding Foreground, ElementName=userControl}"
StrokeThickness="{Binding Thickness, ElementName=userControl}"
X1="{Binding X1, ElementName=userControl, Mode=OneWay}"
X2="{Binding X2, ElementName=userControl, Mode=OneWay}"
Y1="{Binding Y1, ElementName=userControl, Mode=OneWay}"
Y2="{Binding Y2, ElementName=userControl, Mode=OneWay}" />
<Line Stroke="{Binding Foreground, ElementName=userControl}"
StrokeThickness="{Binding Thickness, ElementName=userControl}"
X1="{Binding X2, ElementName=userControl, Mode=OneWay}"
X2="{Binding X1, ElementName=userControl, Mode=OneWay}"
Y1="{Binding Y1, ElementName=userControl, Mode=OneWay}"
Y2="{Binding Y2, ElementName=userControl, Mode=OneWay}"/>
</Grid>
</UserControl>
我的Cross.xaml.cs:
public partial class Cross : UserControl
{
public Cross()
{
InitializeComponent();
}
public readonly static DependencyProperty CenterPointProperty = DependencyProperty.Register("CenterPoint",
typeof(PointF), typeof(Cross),
new PropertyMetadata(default(PointF)));
public PointF CenterPoint
{
get { return (PointF)GetValue(CenterPointProperty); }
set { SetValue(CenterPointProperty, value); }
}
public readonly static DependencyProperty ThicknessProperty = DependencyProperty.Register("Thickness",
typeof(int), typeof(Cross),
new PropertyMetadata(2));
public int Thickness
{
get { return (int)GetValue(ThicknessProperty); }
set { SetValue(ThicknessProperty, value); }
}
public float X1
{
get
{
return (float)(CenterPoint.X - (Width / 2));
}
}
public float X2
{
get
{
return (float)(CenterPoint.X + (Width / 2));
}
}
public float Y1
{
get
{
return (float)(CenterPoint.Y - (Height / 2));
}
}
public float Y2
{
get
{
return (float)(CenterPoint.Y + (Height / 2));
}
}
}
我可以这样称呼:
<local:Cross CenterPoint="{Binding Point}" Thickness="8" Foreground="Yellow" Height="40" Width="40"/>
我遇到问题,不显示十字架。我添加了断点,当我更改CenterPoint时,似乎值X1,X2,...不会刷新。如何强制C#重新评估这些值? (希望这能解决我的问题)
谢谢
答案 0 :(得分:2)
如果希望在将CenterPoint依赖项属性设置为新值时刷新X1,X2,Y1和Y2只读属性,则UserControl应实现INotifyPropertyChanged
接口。然后,您可以为依赖项属性注册PropertyChangedCallback
,并为只读属性引发PropertyChanged
事件:
public partial class Cross : UserControl, INotifyPropertyChanged
{
public Cross()
{
InitializeComponent();
}
public readonly static DependencyProperty CenterPointProperty = DependencyProperty.Register("CenterPoint",
typeof(PointF), typeof(Cross),
new PropertyMetadata(default(PointF), new PropertyChangedCallback(OnCenterPointUpdated))));
private static void OnCenterPointUpdated(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Cross cross = d as Cross;
cross.NotifyPropertyChanged("X1");
cross.NotifyPropertyChanged("X2");
cross.NotifyPropertyChanged("Y1");
cross.NotifyPropertyChanged("Y2");
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
...
}
答案 1 :(得分:1)
mm8的方法可用于更新X1
等,但还需要解决其他问题才能使控制工作。
我正在使用另一种方法来更新坐标属性:将X1
等转换为read-only dependency properties,让用户控件在CenterPoint
更改时以及控件的大小更改时更新它们。
我还将您的winforms PointF
更改为WPF System.Windows.Point
,double
使用X
和Y
,我已更改{ {1}}到Thickness
,因为WPF使用float
来表示线条粗细,您也可以充分利用它。
我正在更新float
事件的坐标,这是至关重要的,因为否则,只有当实际大小为0 x 0时才会在控件创建时设置坐标属性,SizeChanged
Width
是Height
。
最后,您应该使用NaN
和ActualWidth
,这些更新为“实时”,而不是ActualHeight
和Height
,它们是设计时属性值。如果您给它一个固定的Width
和Width
,效果将是相同的;使用Height
和ActualWidth
允许它伸展以适合容器(如果需要)。
ActualHeight
最后,您不需要明确地设置绑定public partial class Cross : UserControl
{
public Cross()
{
InitializeComponent();
SizeChanged += Cross_SizeChanged;
}
private void Cross_SizeChanged(object sender, SizeChangedEventArgs e)
{
UpdateXYProperties();
}
protected void UpdateXYProperties()
{
X1 = (float)(CenterPoint.X - (ActualWidth / 2));
X2 = (float)(CenterPoint.X + (ActualWidth / 2));
Y1 = (float)(CenterPoint.Y - (ActualHeight / 2));
Y2 = (float)(CenterPoint.Y + (ActualHeight / 2));
}
public readonly static DependencyProperty CenterPointProperty = DependencyProperty.Register(nameof(CenterPoint),
typeof(Point), typeof(Cross),
new PropertyMetadata(default(Point), CenterPoint_PropertyChanged));
private static void CenterPoint_PropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
((Cross)obj).UpdateXYProperties();
}
public Point CenterPoint
{
get { return (Point)GetValue(CenterPointProperty); }
set { SetValue(CenterPointProperty, value); }
}
public readonly static DependencyProperty ThicknessProperty = DependencyProperty.Register(nameof(Thickness),
typeof(float), typeof(Cross),
new PropertyMetadata(2.0F));
public float Thickness
{
get { return (float)GetValue(ThicknessProperty); }
set { SetValue(ThicknessProperty, value); }
}
#region Read-Only Properties
#region X1 Property
public float X1
{
get { return (float)GetValue(X1Property); }
protected set { SetValue(X1PropertyKey, value); }
}
internal static readonly DependencyPropertyKey X1PropertyKey =
DependencyProperty.RegisterReadOnly("X1", typeof(float), typeof(Cross),
new PropertyMetadata(0.0F));
public static readonly DependencyProperty X1Property = X1PropertyKey.DependencyProperty;
#endregion X1 Property
#region X2 Property
public float X2
{
get { return (float)GetValue(X2Property); }
protected set { SetValue(X2PropertyKey, value); }
}
internal static readonly DependencyPropertyKey X2PropertyKey =
DependencyProperty.RegisterReadOnly("X2", typeof(float), typeof(Cross),
new PropertyMetadata(0.0F));
public static readonly DependencyProperty X2Property = X2PropertyKey.DependencyProperty;
#endregion X2 Property
#region Y1 Property
public float Y1
{
get { return (float)GetValue(Y1Property); }
protected set { SetValue(Y1PropertyKey, value); }
}
internal static readonly DependencyPropertyKey Y1PropertyKey =
DependencyProperty.RegisterReadOnly("Y1", typeof(float), typeof(Cross),
new PropertyMetadata(0.0F));
public static readonly DependencyProperty Y1Property = Y1PropertyKey.DependencyProperty;
#endregion Y1 Property
#region Y2 Property
public float Y2
{
get { return (float)GetValue(Y2Property); }
protected set { SetValue(Y2PropertyKey, value); }
}
internal static readonly DependencyPropertyKey Y2PropertyKey =
DependencyProperty.RegisterReadOnly("Y2", typeof(float), typeof(Cross),
new PropertyMetadata(0.0F));
public static readonly DependencyProperty Y2Property = Y2PropertyKey.DependencyProperty;
#endregion Y2 Property
#endregion Read-Only Properties
}
,因为Mode=OneWay
等无法更新绑定源(在这种情况下,这是您自己的Line.X1
等),所以默认情况下它们已经X1
。
OneWay
最后,几乎可以肯定:<Grid>
<Line
Stroke="{Binding Foreground, ElementName=userControl}"
StrokeThickness="{Binding Thickness, ElementName=userControl}"
X1="{Binding X1, ElementName=userControl}"
X2="{Binding X2, ElementName=userControl}"
Y1="{Binding Y1, ElementName=userControl}"
Y2="{Binding Y2, ElementName=userControl}"
/>
<Line
Stroke="{Binding Foreground, ElementName=userControl}"
StrokeThickness="{Binding Thickness, ElementName=userControl}"
X1="{Binding X2, ElementName=userControl}"
X2="{Binding X1, ElementName=userControl}"
Y1="{Binding Y1, ElementName=userControl}"
Y2="{Binding Y2, ElementName=userControl}"
/>
</Grid>
设计的效果是,如果它不是控件的实际中心,则偏移控件边界外的交叉。如果这是你的意图,不要费心阅读本段的其余部分。如果这不是您的意图,您可以按如下方式重写CenterPoint
并丢失UpdateXYProperties()
属性:
CenterPoint
但这取决于你和圣安德鲁。