我们有一个DependencyObject,它将Value属性定义为DP。它还定义了一个Presets集合,表示某些预定义值的友好名称。
我们的UI应该工作的方式是当我们绑定到Value属性时,如果值与预设匹配,我们会显示友好名称,否则我们只是直接显示值。
使用转换器是因为没有可靠的方法来传递预设(每个项目定义,它们不是共享的)并且还进行双向绑定,所以我们的想法是暴露一个FriendlyValue属性在对象上使用它并在UI中进行绑定,让它在内部处理转换。
由于FriendlyValue依赖于已存在的Value DependencyProperty,我们认为我们只是将转换逻辑包装在CLR getter / setter中,但这意味着当实际的值DP发生变化时,它需要通知UI FriendlyValue已经也更新了,因为FriendlyValue是一个CLR属性,我们需要为该特定属性支持INPC。
我的问题是,是正确/建议的方法来处理这个,或者我应该使用第二个DP,监视其更改处理程序并相应地设置其他属性,添加状态变量以阻止一个设置另一个,然后设置第一个,然后再次更新另一个,等等。
以下是对象属性的代码......
public static readonly DependencyProperty PresetsProperty = DependencyProperty.Register(
"Presets",
typeof(List<Preset>),
typeof(MyObject),
new UIPropertyMetadata(null));
public List<Preset> Presets
{
get { return (List<Preset>)GetValue(PresetsProperty); }
set { SetValue(PresetsProperty, value); }
}
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
"Value",
typeof(string),
typeof(MyObject),
new UIPropertyMetadata(null, (s,e) => {
var myObject = (MyObject)s;
myObject.OnPropertyChanged("FriendlyValue");
}));
public string Value
{
get { return (string)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public string FriendlyValue
{
get
{
var foundPreset = Presets.FirstOrDefault(preset => preset.Value == this.Value);
return (foundPreset != null)
? foundPreset.FriendlyName
: this.Value;
}
set
{
var foundPreset = Presets.FirstOrDefault(preset => preset.FriendlyName == value);
this.Value = (foundPreset != null)
? foundPreset.Value
: value;
// Note: We don't raise INPC notification here. It's raised in the Value's change handler
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if(PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
对于内置转换器行为,这被认为是一种很好的做法吗?
答案 0 :(得分:0)
为什么不同时生成Value
和FriendlyValue
依赖项属性?我认为没有理由同时使用两种技术。
考虑:
using Preset = Tuple<string, string>;
public class MyObject : DependencyObject
{
private readonly IList<Tuple<string, string>> _presets = new List<Preset> {
new Preset("1", "good"),
new Preset("2", "bad"),
};
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
"Value", typeof(string), typeof(MyObject),
new PropertyMetadata(null,
(o, e) => ((MyObject)o).ValuePropertyChanged((string)e.NewValue)));
private static readonly DependencyProperty FriendlyValueProperty = DependencyProperty.Register(
"FriendlyValue", typeof(string), typeof(MyObject),
new PropertyMetadata(null,
(o, e) => ((MyObject)o).FriendlyValuePropertyChanged((string)e.NewValue)));
public string Value
{
get { return (string)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public string FriendlyValue
{
get { return (string)GetValue(FriendlyValueProperty); }
set { SetValue(FriendlyValueProperty, value); }
}
private void ValuePropertyChanged (string newValue)
{
var preset = _presets.FirstOrDefault(p => p.Item1 == newValue);
FriendlyValue = preset != null ? preset.Item2 : newValue;
}
private void FriendlyValuePropertyChanged (string newValue)
{
var preset = _presets.FirstOrDefault(p => p.Item2 == newValue);
Value = preset != null ? preset.Item1 : newValue;
}
}
注意:
我希望我能正确理解你的逻辑。有一个问题:如果您将FriendlyValue
更改为预设中的一个友好值,则会将Value
更改为找到的预设中的值,然后将FriendlyValue
更改为名称预设。我不知道这种行为是否是预期的。