代码改变世界

WPF:数据绑定中的Path

2014-07-28 11:28  Desmond  阅读(2809)  评论(0)    收藏  举报

"每个绑定通常都具有四个组件:绑定目标对象、目标属性、绑定源,以及要使用的绑定源值的路径。"在msdn中对数据绑定有这样的解释。"使用的绑定源值的路径",也就是Binding的Path属性。在有些数据绑定中,我并没有设置它,以至于再更新绑定时,界面并没有更新。下面通过各简单示例对比一下,以加深记忆,和对遇到同样问题的码农们些提示。我发现是Path的原因,还是花了些时间的。

示例:显示学生的姓名,姓和名加一个空格。

学生实体

class Student : INotifyPropertyChanged
{
    private string _name;

    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            RaiseProertyChanged("Name");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void RaiseProertyChanged(string propName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }
}

定义两个值转换器,一个转换Name,一个转换Student

class ValueConverterWithPath : IValueConverter
{

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string name = (string)value;
        if (string.IsNullOrEmpty(name))
        {
            throw new FormatException("Name长度为0或者为null");
        }
        return name.Insert(1, " ");
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

class ValueConverterWithoutPath : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        Student student = value as Student;
        if (student == null)
        {
            throw new NullReferenceException("数据源为null");
        }
        string name = student.Name;
        if (string.IsNullOrEmpty(name))
        {
            throw new FormatException("Name长度为0或者为null");
        }
        return name.Insert(1, " ");
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

界面xaml

<StackPanel>
    <StackPanel.Resources>
        <local:ValueConverterWithoutPath x:Key="valueConverterWithoutPath" />
        <local:ValueConverterWithPath x:Key="valueConverterWithPath" />
    </StackPanel.Resources>
    <DockPanel Margin="3" LastChildFill="False">
        <TextBlock Width="200"
                   DockPanel.Dock="Left"
                   Text="使用Path绑定" />
        <TextBlock  Text="{Binding Path=Name, Converter={StaticResource valueConverterWithPath}}" />
    </DockPanel>
    <DockPanel Margin="3" LastChildFill="False">
        <TextBlock Width="200"
                   DockPanel.Dock="Left"
                   Text="不使用Path绑定" />
        <TextBlock Text="{Binding Converter={StaticResource valueConverterWithoutPath}}" />
    </DockPanel>
    <Button HorizontalAlignment="Left"
            Click="ChangeName"
            Content="Change Name" />
</StackPanel>

后台代码

public partial class MainWindow : Window
{
    private Student _student;

    public MainWindow()
    {
        InitializeComponent();
        _student = new Student { Name = "周星星" };
        this.DataContext = _student;
    }

    private void ChangeName(object sender, RoutedEventArgs e)
    {
        _student.Name = "周星驰";
    }
}

下面是得到的效果

没有使用Path的数据绑定,界面并没有更新。
如果想知道更深的原因,可以反编译Binding类,我觉得没有必要,就到此为止吧。