如何使用与路径不同的源数据绑定到CLR对象

时间:2011-08-04 09:35:22

标签: wpf data-binding mvvm

我试图通过数据绑定到viewmodel中的属性(视图的datacontext)来更新视图上的文本块。

在下面的代码中;当 SelectedItem 发生变化时,我希望使用 SelectedItem 名称属性的值更新文本块文本。

为了实现这一目标,我将绑定源设置为正在更改的属性,将绑定路径设置为我想要更新文本块的数据。

即。我期待绑定引擎会在绑定Source(SelectedItem)上看到更改,并从绑定路径(SelectedItem.Name)中提取数据。

http://msdn.microsoft.com/en-us/library/ms746695.aspx

设置SelectedItem会引发INPC,但文本不会更新。

public class ViewModel
{
     public IConfiguration Configuration { get; set;}
}

public class Configuration : IConfiguration, INotifyPropertyChanged
{
    public Item SelectedItem
    {
       get { return _item;}
       set
       {
           _item = value;
           ItemName = _item.Name;
           RaisePropertyChangedEvent("SelectedItem");
       }
    }

  public string ItemName 
  {
       get { return _itemName;}
       set
       {
           _itemName= value;
           RaisePropertyChangedEvent("ItemName");
       }
    }
}

public class Item
{
   public string Name { get; set;}
}

我知道可以看到配置上的更改,因为它有效:

<TextBlock Text="{Binding Configuration.ItemName}"/>

但这不是:

<TextBlock Text="{Binding Path=Name, Source=Configuration.SelectedItem}"/>

这也不是:

<TextBlock Text="{Binding Path=Configuration.SelectedItem.Name, Source=Configuration.SelectedItem}"/>

我认为这应该是直截了当的 - 我错过了什么?

2 个答案:

答案 0 :(得分:3)

我以前从未见过有人使用Binding.Source,所以我对此并不了解。但我的猜测是它不是动态的。当您创建绑定时,它会抓取对Source中指定的对象的引用,然后就是它:它在绑定的生命周期中使用相同的引用。

为什么要这么复杂?只需使用Path即可。这是进行绑定的常规方式,它一直是动态的 - 你所做的正是Path的目的。

<TextBlock Text="{Binding Path=Configuration.SelectedItem.Name}"/>

答案 1 :(得分:0)

这可能有效,你就是看不到它。尚未通知Binding引擎Item对象的Name属性已更改。

尝试在Item类上实现INotifyPropertyChanged接口(根据需要引发PropertyChanged事件)

这适用于您的第三种绑定情况,也适用于下面的类似定义

<TextBlock DataContext="{Binding Path=Configuration.SelectedItem}" Text="{Binding Path=Name}"/>

但是对于更简单的修复,这应该有效:

<TextBlock Text="{Binding Path=Configuration.SelectedItem.Name}" />

编辑:

public class Configuration : INotifyPropertyChanged
{
    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion

    private Item _SelectedItem = null;
    public Item SelectedItem
    {
        get
        {
            return _SelectedItem;
        }
        set
        {
            _SelectedItem = value;
            OnPropertyChanged("SelectedItem");
        }
    }
}

public class Item
{
    public string Name { get; set; }
}

然后在某个地方的命令执行中我有这个:

Configuration.SelectedItem = new Item() { Name = "test" };

在View中正确更新TextBlock:

<TextBlock Text="{Binding Path=Configuration.SelectedItem.Name}" />