ItemsControl绑定错误

时间:2018-05-07 19:58:59

标签: c# wpf data-binding itemscontrol

我在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类的属性的路径。

1 个答案:

答案 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,这不是真正的绘图宽度。您需要将WidthHeightStrokeStrokeThickness等设置为自定义形状,然后您需要从{{{{{}完全删除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,因为我没有使用它来制作示例。如果您复制并粘贴,请不要忘记将其添加回来。