WPF自定义控件,将模型作为依赖属性

3

是否可以将模型作为自定义控件的DependencyProperty使用?我想这样做是因为我想创建一个自定义控件,它基本上是一个图像绘制器,用于绘制名称和数据点列表。

类似于这样:

模型:

public class Draw : NotificationObject
{

public Draw(string name, List<System.Drawing.PointF> data)
    {
        Name = name;
        Data = data;

    }

    private string _name;
    public string Name
    {
        get { return _name; }
        set
        {
            if (_name != value)
            {
                _name = value;
                RaisePropertyChanged(() => Name);
            }
        }
    }

    private List<System.Drawing.PointF> _data;
    public List<System.Drawing.PointF> Data
    {
        get { return _data; }
        set
        {
            if (_data != value)
            {
                _data = value;
                RaisePropertyChanged(() => Data);
            }
        }
    }
}
}

自定义控件:

public class MyCanvas: System.Windows.Controls.Image
{
   static void itemsChangedCallBack(DependencyObject property,
   DependencyPropertyChangedEventArgs args)
    {
        MyCanvas searchTextBox = (MyCanvas)property;
        Console.WriteLine("got update");
        searchTextBox.Items = (Draw)args.NewValue;
    }

   public static readonly DependencyProperty ItemsProperty =
   DependencyProperty.Register("Items",
   typeof(Draw),
   typeof(MyCanvas),new PropertyMetadata(new PropertyChangedCallback(itemsChangedCallBack)));

    public Draw Items
    {
        get { return (Draw)GetValue(ItemsProperty); }
        set { SetValue(ItemsProperty, value); }
    }
}

当然还有XAML:

<myClass:MyCanvas x:Name="Canvas1" Items="{Binding drawModel,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" SizX="1600" SizY="200" />

而ViewModel调用:

public class MainWindowViewModel : BaseViewModel
   {

   public Draw drawModel { get; set; }

   public MainWindowViewModel()
       {
           drawModel = new Draw("first", null); // custom control is notified
       }

   private someFunction() //within another thread but should not matter
       {
           drawModel.Data = newData; // custom control should be notified but is not
       }
}

我的问题是,如果我在ViewModel中更改drawModel.Data(属性),我就无法通知自定义控件。我以前用一个简单的字符串而不是模型实现过它并且有效。它能够在第一次初始化drawModel时工作,但如果稍后更新Data属性,则无法工作。


1
是的,这是可能的...你的代码有什么问题吗? - Sheridan
是的,这是可能的,你的代码看起来很好。只需要将 typeof(DPFCanvas) 改为 typeof(MyCanvas) 即可。 - Nitin
如果您希望在绑定中反映更新,您需要在模型类上实现INotifyPropertyChanged - Dan Puzey
我正在使用NotificationObject。我现在将其添加到帖子中,因为我之前忽略了它,因为我认为它很明显,否则我就不会收到任何通知。你有什么想法? - user2799180
问题仍然存在。有人能帮我弄清楚为什么它不起作用吗? - user2799180
2个回答

2
它在drawModel第一次初始化时有效,但如果稍后更新Data属性,则无效。
你应该将Data设置为ObservableCollection(或者更好的是ObservableCollection,因为WPF的Point已经支持浮点值)。
问题在于添加、删除或更改List不会向WPF提供任何形式的通知,表明事情已经发生了变化。ObservableCollection实现了INotifyCollectionChanged,这是INotifyPropertyChanged的集合版本。
请注意,这仍然不会触发控件内部的更新。如果您需要,可以订阅Draw.Data的CollectionChanged事件以便在集合内部发生更改时得到通知。

0

您的视图模型没有实现INotifiyPropertyChanged,在构造函数中首次设置属性drawModel,此时UI尚未完全创建,并且一旦UI创建完成并加载后,它将加载属性的当前值,但是当再次更改该值时,您必须通知UI特定属性的值已更改。

如果您更改了Draw类中任何属性的值,则可以反映出来,因为它实现了INotifiyPropertyChanged,但您正在更改位于视图模型中的drawModel的值,这不实现INotifiyPropertyChanged,因此不会更新


你的 BaseViewModel 是否实现了 INotifyPropertyChanged 接口?如果是,则在 drawModel 属性的 setter 中调用 RaisePropertyChanged 方法。如果你的 BaseViewModel 没有实现 INotifyPropertyChanged 接口,则在 MainWindowViewModel 中实现它。 - Kumareshan
模型和MainViewModel已经实现了INotifyPropertyChanged。如果我更改drawModel.Data属性,我可以在MainViewModel和View中看到更改。自定义控件没有收到通知。我应该提供源代码吗? - user2799180
让我们在聊天中继续这个讨论:http://chat.stackoverflow.com/rooms/39857/discussion-between-user2799180-and-kumareshan - user2799180
我查看了你的代码,但是只找到了部分代码,无法找到完整的代码。不过没关系,这并不重要。 - Kumareshan
你正在更改Draw类中存在的属性Data的值,因此你将在Draw类中收到通知,而不是在你的自定义控件类中。如果你想让你的自定义控件类得到通知,则需要在Draw类中公开一个委托,并在Draw类中收到通知时调用该委托。在你的自定义控件类中连接到Draw类中公开的委托即可。如果你不理解,请告诉我,我会尝试为你提供一个示例。 - Kumareshan
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接