1

我最近开始试验 DataBinding 并为我的自定义类实现 DependencyProperties。这一切都很好,而且可能性令人兴奋,但是,我遇到了一个可能只能通过稍微修改整体类设计来解决的问题。我想确保这是唯一的选择,而且我没有遗漏任何东西。

因此,我的班级存储有关用户导入应用程序的视频文件的信息。除其他属性外,它还包含:

public class VideoFile {

    public string FilePath { get; protected set; }
    public uint ID { get; protected set; ]
    public string Extension { get { return Path.GetExtension(FilePath); } }
    public string FileName { get { return Path.GetFilename(FilePath); } }

}

所以,我已经成功地将 FilePath 替换为 DependencyProperty。但是,在 UI 中,我主要想只显示文件名,它使用一些逻辑来提供其值。据我所知,这是我的选择:

  1. 我可以简单地为 FileName 和 Extension 创建 DependencyProperties,并在构造函数中设置它们的值,但这是多余的;我已经在 FilePath 中有这些信息,所以我想避免这个选项。
  2. 创建 ValueConverters,一个用于显示文件名,一个用于显示扩展名,并在我的绑定中使用它们。

我只是简单地遇到了 ValueConverters,所以我不确定。我可以将它们用于此目的吗?或者,我是否刚刚遇到了它们存在的主要原因之一?:)

最后但并非最不重要的一点是,当 ValueConverter 不是正确的方法时,谁能想到类似的情况?我想避免直接跳入它们,只是意识到它不起作用,因为“那个”属性不能以这种方式表达。

4

3 回答 3

1

你不需要DependencyProperties这个。DependencyProperty当您要使用 a 设置属性,您只需要 a MarkupExtension,我怀疑您是否使用模型类来执行此操作(因为您不会在 Xaml 中声明此类!)。

一种更轻量级的方法是使用INotifyPropertyChanged. 这是一个 .NET 3.5 风格的实现:

public class VideoFile : INotifyPropertyChanged
{
    private string _filePath;

    public string FilePath
    {
        get
        {
            return _filePath;
        }
        protected set
        {
            _filePath = value;
            OnPropertyChanged("FilePath");
            OnPropertyChanged("Extension");
            OnPropertyChanged("FileName");
        }
    }

    public uint ID { get; protected set; }
    public string Extension { get { return Path.GetExtension(FilePath); } }
    public string FileName { get { return Path.GetFileName(FilePath); } }

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

    public event PropertyChangedEventHandler PropertyChanged;
}

[CallerMemberName](在 .NET 4.5 中,由于新属性,这可以稍微简化。)

唯一的缺点是您的属性需要支持字段。但是,有一个名为 NotifyPropertyWeaver 的 VS 扩展可以自动完成部分工作,并且也无需显式支持属性。

于 2012-09-17T13:16:24.807 回答
0

不要重复数据。

PreferBinding和 an IValueConverter,因为这样,每当FilePath更改时,Extension也会FileName在 UI 中更新。

当然,您也可以PropertyChanged在 's setter 中为他们加注,FilePath但这是不好的做法,因为FilePath不必关心谁/什么使用它。

然后类看起来像:

public class VideoFile : INotifyPropertyChanged {

    string m_FilePath;
    public string FilePath 
    { 
       get { return m_FilePath; } 
       protected set
       {
          if(value != m_FilePath)
          {
             m_FilePath = value;
             RaisePropertyChanged(() => this.FilePath);
          }
       }
    }
    public uint ID { get; protected set; }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;
    protected void RaisePropertyChanged<T>(Expression<Func<T>> _PropertyExpression)
    {
        RaisePropertyChanged(PropertySupport.ExtractPropertyName(_PropertyExpression));
    }

    protected void RaisePropertyChanged(String _Prop)
    {
        PropertyChangedEventHandler handler = this.PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(_Prop));
        }
    }

    #endregion
}

请注意,它PropertySupport是 Prism 的一部分,但您可以通过调用 不使用它,RaisePropertyChanged("FilePath")具有类型安全性非常好,因为如果您更改属性的名称,您将遇到编译时错误。

于 2012-09-17T12:53:52.303 回答
0

据我了解,您只想在 UI 上显示文件名。然后,您可以考虑在 FilePath 依赖属性更改时更新 FileName 属性(OnChangedFilePath 方法)。您还可以在 ValidateFilePath 方法中检查 FilePath 是否正常。请注意,FileName 也必须是依赖属性或支持 IPropertyChanged,否则更改时 UI 不会更新。您不需要为此目的使用转换器。

public string FilePath
{
    get { return (string)GetValue(FilePathProperty); }
    set { SetValue(FilePathProperty, value); }
}

private static object CoerceFilePath(DependencyObject d, object value)
{
    return value;
}

private static bool ValidateFilePath(object Value)
{
    return true;
}

private static void OnChangedFilePath(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
}

public static readonly DependencyProperty FilePathProperty =
    DependencyProperty.Register("FilePath", typeof(string), typeof(ClassName),
    new PropertyMetadata(@"C:\File.avi", OnChangedFilePath, CoerceFilePath),
    new ValidateValueCallback(ClassName.ValidateFilePath));
于 2012-09-17T13:08:18.770 回答