WPF,将DataContext设置为同一类的属性

时间:2016-05-06 13:40:25

标签: c# wpf data-binding blend

我有一个使用Device的课程INotifyPropertyChanged,经过测试并且有效。

现在我有一个deviceMonitor,它是此设备的UI表示形式。在代码中我引用了Device,我想将设备中的更改链接到UI中的更改(不需要两种方式,但单击deviceMonitor应该调用{的某个函数{1}})

我正在使用表达式Blend和VS2015,因此非常欢迎基于点击以使其工作的指导。

这是device

的模型
device

然后是GUI的xaml.cs,这里我引用了包含public class Device : INotifyPropertyChanged { public string Name { ... } //uses NotifyPropertyChanged in the set // other properties and their relative private vars. } 的dll:

Device

然后是XAML

public partial class DeviceControl : UserControl
{
   public Device myDevice = new Device();

   public DeviceControl()
    {
        InitializeComponent();
        // here I tried setting the datacontest to the myDevice

        // also tried to set the dataContext in Blend and here grab a
        // reference to it and store it in myDevice. But nothing workerd
    }

    public void ChangeDevName()
    {
         this.myDevice.DeviceName = "Test";
         //UI Representation of deviceName never changed
    }
}

2 个答案:

答案 0 :(得分:0)

这可能有效:

DeviceControl UserControl中,为控件的OnLoadedOnUnloaded发送事件。

在事件处理程序的代码隐藏中,订阅/取消订阅UserControl的DataContext(PropertyChanged)的this.DataContext事件;像这样:

private void OnLoaded(object sender, RoutedEventArgs e)
{
    if (this.DataContext is INotifyPropertyChanged)
    {
        ((INotifyPropertyChanged)this.DataContext).PropertyChanged += OnDataContextPropertyChanged;
    }
}

private void OnUnloaded(object sender, RoutedEventArgs e)
{
    if (this.DataContext is INotifyPropertyChanged)
    {
        ((INotifyPropertyChanged)this.DataContext).PropertyChanged -= OnDataContextPropertyChanged;
    }
}

private void OnDataContextPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    // You could also just update every time something is changed.
    // As an example you could check for the "Name" property being changed.
    if (e.PropertyName == nameof(Device.Name))
    {
        title.Text = this.DataContext.Name;
    }
}

要做的重要提示是if (this.myDevice is INotifyPropertyChanged)检查。

确保Device类继承自INotifyPropertyChanged

提供它,它会将Device作为您的DataContext(this.DataContext)投射到(INotifyPropertyChanged),以便您可以从PropertyChanged订阅INotifyPropertyChanged事件接口

然后,当DataContext上的属性发生更改时,将触发您的处理程序。显然你可以在OnMyDevicePropertyChanged的代码中放置你想做的事情,我只是用“名字”作为例子。

希望这有帮助!

修改 此外;您还可以在UserControl的代码隐藏中存储类型为Device的私有字段。有点像:

private Device _viewModel; // You could also use the interface (like 'IDevice'), too.

然后在你的`OnLoaded'事件中,将它存储在字段中:

if (this.DataContext is INotifyPropertyChanged)
{
    this.viewModel = this.DataContext;

    // Wire up your PropertyChanged handler as before.
}

在您的OnUnloaded事件中,如果它不为null,则取消订阅viewModel:

if (this.viewModel != null)
{
    this.viewModel.PropertyChanged -= OnDataContextPropertyChanged;
}

当您将DataContext存储为字段时,这也为您提供了更多的灵活性,因为您可以在其他方法中使用它(如果您在代码中使用了更多 - 您不应该。 .. ;但它可以节省CPU时间,使其一直投入INotifyPropertyChanged。

为了将来参考,我会在您的项目中查看Implementing MVVM Practices

祝你好运!

答案 1 :(得分:0)

问题是覆盖私有设备,设置datacontext固定的东西。 这是最后一堂课:

public partial class DeviceControl : UserControl

private Device _device = new Device();

public DeviceControl()
{
    InitializeComponnents();
    this.DataContext = _device;
}

public void SetDevice(Device d)
{
    //This fails:
    //_device = d;

    //This works
    this.DataContext = d;
 }