我在ItemsControl中有一个Canvas,其ItemsSource是一个ObservableCollection。这是一个Rectangle,其Width属性绑定到RectangleOverlay的wWdith属性。无论我尝试过什么,宽度都显示为0我试过搬东西。 这是视图。
<Grid>
<Label HorizontalAlignment="Center"
Content="IMAGE FROM CAMERA"
Width="Auto" FontFamily="White"
Canvas.Left="50" Panel.ZIndex="2"/>
<ItemsControl Panel.ZIndex="3"
ItemsSource="{Binding Source=MyProperty}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Canvas Height="Auto" >
<Rectangle Width="{Binding Path=wWidth,
UpdateSourceTrigger=PropertyChanged}"
Height="50"
Canvas.Left="50"
Canvas.Top="50"
Stroke="Red"
StrokeThickness="2"/>
<TextBox Canvas.Left="50"
Canvas.Top="100"
Text="TEXT"/>
</Canvas>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
这是RectangleOverlay类的代码
public class RectOverlay : Shape, INotifyPropertyChanged
{
public RectOverlay()
{
}
//I DONT KNOW WHAT EXACTLY NEEDS TO BE IN HERE
protected override Geometry DefiningGeometry
{
get { return new RectangleGeometry();}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
private double _width;
public double wWidth
{
get { return _width; }
set
{
_width = value;
OnPropertyChanged("wWidth");
}
}
}
这里有大部分代码(MainWindow.xaml.cs)。
public partial class MainWindow : Window, INotifyPropertyChanged
{
private ObservableCollection<RectOverlay> ListShapes;
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
MyProperty = new ObservableCollection<RectOverlay>();
ListShapes.Add(new RectOverlay() { wWidth = 100 });
_timer = new Timer(2000); // Set up the timer for 3 seconds
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
_timer.Enabled = true; // Enable it
}
public ObservableCollection<RectOverlay> MyProperty
{
get { return ListShapes; }
set
{
ListShapes = value;
OnPropertyChanged("MyProperty");
}
}
}
我似乎无法理解绑定失败的原因。
System.Windows.Data Error: 40 : BindingExpression path error: 'wWidth' property not found on 'object' ''Char' (HashCode=5046349)'. BindingExpression:Path=wWidth; DataItem='Char' (HashCode=5046349); target element is 'Rectangle' (Name=''); target property is 'Width' (type 'Double')
我读过&amp;试图从SO上的其他类似帖子中弄清楚如何推断这个错误。我想我已经正确设置了绑定流程。整个窗口的数据上下文是后面的代码,在ItemsControl Source之后是自定义类(RectangleOverlay)的ObservableCollection。 &安培;在数据模板中,我正在设置我的Custom类的属性的路径。
答案 0 :(得分:0)
第一个错误是你写的
ItemsSource="{Binding Source=MyProperty}"
而不是
ItemsSource="{Binding Path=MyProperty}"
或只是
ItemsSource="{Binding MyProperty}"
将Bindings的Source对象设置为MyProperty
只是指定字符串文字"MyProperty"
,它是一个IE的数量的Chars,因此被解释为。
ItemTemplate中的Binding然后不可避免地抱怨它在wWidth
类型的对象上找不到Char
属性。
但是你面临着另一个问题。这是正确答案,说实话,我不得不为你得到这个......我以前从未遇到过这个问题。
首先,由于您使用的是自定义形状,ItemsControl
会忽略自定义DataTemplate
并尝试绘制您提供的RectOverlay
。
现在你当然没有看到这个,因为你只设置它的wWidth
,这不是真正的绘图宽度。您需要将Width
,Height
,Stroke
,StrokeThickness
等设置为自定义形状,然后您需要从{{{{{}完全删除DataTemplate
1}}。
然而,一旦你这样做,你仍然会注意到它没有画画。这是因为您的XAML
返回空白DefiningGeometry
。这需要是您打算绘制的路径等。 (如果以后需要,请提供更多信息。)
所有这一切,我真的觉得你不需要这里的自定义形状;如果你这样做,请给出完整的要求,我将提供一个工作的自定义形状和显示有效。我在我的机器上做到了,但是我不会发布那些代码,因为我认为这不是你真正需要的。
另一件需要注意的事项......如果您使用的是自定义形状,则它来自RectangleGeometry
类型。这意味着实施DependencyObject
是过度的。您只需使用自定义INotifyPropertyChanged
即可。
请查看下面的代码。我将RectOverlay修改为更多的ViewModel,并将DependencyProperty
中的MyProperty
更新为MainWindow
。
以下是
背后的DependencyProperty
代码
MainWindow
以下是ViewModel public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
MyProperty.Add(new RectOverlay() { wWidth = 100 });
}
public ObservableCollection<RectOverlay> MyProperty
{
get { return (ObservableCollection<RectOverlay>)GetValue(MyPropertyProperty); }
set { SetValue(MyPropertyProperty, value); }
}
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register(nameof(MyProperty), typeof(ObservableCollection<RectOverlay>), typeof(MainWindow), new PropertyMetadata(new ObservableCollection<RectOverlay>()));
}
RectOverlay
我按照您的方式离开public class RectOverlay : INotifyPropertyChanged
{
private double wwidth;
public double wWidth
{
get { return wwidth; }
set
{
wwidth = value;
OnPropertyChanged(nameof(wWidth));
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
(除了删除Source =)
如果您确定自己需要自定义XAML
,那么我也可以实现这一目标,但也请告诉我您的用例,以便我能够做到正确。
另外,我删除了_timer,因为我没有使用它来制作示例。如果您复制并粘贴,请不要忘记将其添加回来。