我最近开始尝试使用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); } }
}
所以,我已成功用DependencyProperty替换了FilePath。但是,在UI中,我主要想显示文件名,它使用一些逻辑来提供其值。据我所知,这是我的选择:
我只是简单地遇到了ValueConverters,所以我不确定。我可以将它们用于此目的吗?或者,我刚刚遇到他们存在的主要原因之一? :)
最后但并非最不重要的是,当ValueConverter不是正确的方式时,是否有人能想到类似的情况?我想避免直接进入它们,只是意识到它不起作用,因为“那个”属性不能用这种方式表达。
答案 0 :(得分:1)
您不需要DependencyProperties
。当您要使用DependencyProperty
将设置为属性时,您只需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;
}
(在.NET 4.5中,由于新的[CallerMemberName]
属性,可以稍微简化一下。)
唯一的缺点是您需要为您的属性提供支持字段。但是,有一个名为NotifyPropertyWeaver的VS扩展可以自动完成部分工作,并且不需要显式的后备属性。
答案 1 :(得分:0)
不要复制数据。
首选Binding
和IValueConverter
,因为这样,每当FilePath
更改时,Extension
和FileName
也会在UI中更新。< / p>
当然,你也可以在PropertyChanged
的setter中为他们提出FilePath
,但这是不好的做法,因为FilePath
不应该关心谁/什么使用它。< / p>
该课程如下:
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")
来解决这个问题,只需要安排类型安全,因为如果你更改了属性的名称,你将有一个编译 - 时间错误。
答案 2 :(得分: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));