我有一个带有“ SetState” DependencyProperty的CustomControl。这绑定到具有转换器的MultiBinding(单向)。一切正常。
因此,所有内容均已正确更新,激发了PropertyChanged事件,转换器获取值,生成输出值,但如果(例如)为true且转换器也屈服为true,则SetState属性未更新。由于我要执行重置逻辑(请参见下面的代码),因此我希望SetState始终被更新,即使它将被设置为与当前值相同。 (如果转换器导致false且SetState为true,则SetState将按预期正确更新为false)
MWE(即时输入错误,请输入我的错误)
查看
<local:CustomControl>
<local:CustomControl.SetState>
<MultiBinding Converter="{local:MyConverter}">
<Binding Path="MyProp1" Mode="OneWay" UpdateSourceTrigger="PropertyChanged"/>
<Binding Path="MyProp2" Mode="OneWay" UpdateSourceTrigger="PropertyChanged"/>
</MultiBinding>
</local:CustomControl.SetState>
</local:CustomControl>
自定义控件
public class CustomControl : FrameworkElement
{
public static readonly DependencyProperty IsExpandedProperty = DependencyProperty.Register(
nameof(SetState),
typeof(bool),
typeof(CustomControl),
new FrameworkPropertyMetadata(false, (s, e) =>
{
((CustomControl)s).SetState = (bool)e.NewValue;
}));
private bool _state;
// For brevity i have used a boolean in the MWE
public bool SetState
{
get { return _state; }
set
{
// This is not called when the binding produces the same value as this property already has
// but i want this to be set anyway to trigger the reset logic even though SetState property already equal the value being set.
// Custom reset logic here
_state = value;
}
}
}
转换器
internal class MyConverter : MarkupExtension, IMultiValueConverter
{
private static MyConverter _instance;
public object Convert(object[] value, Type targetType, object parameter, CultureInfo culture)
{
// Imagine some complex logic here
return ((bool)value[0] || (bool)value[1]);
}
public object[] ConvertBack(object value, Type[] targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return _instance ?? (_instance = new MyConverter());
}
}
查看模型
internal class MyViewModel : INotifyPropertyChanged
{
private bool _myProp1;
private bool _myProp2;
// Imagine the properties being altered at run-time
public bool MyProp1
{
get { return _myProp1; }
private set { _myProp1 = value; OnPropertyChanged(); }
}
public bool MyProp2
{
get { return _myProp2; }
private set { _myProp2 = value; OnPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
答案 0 :(得分:0)
该解决方案最终是simple,因为DependencyProperty使用CoerceValueCallback而不是PropertyChangedCallback。始终调用前者,只有在实际更改值时才调用后者。
所以在代码中它变成了
public static readonly DependencyProperty IsExpandedProperty = DependencyProperty.Register(
nameof(SetState),
typeof(bool),
typeof(CustomControl),
new PropertyMetadata(false, null,
(d, v) =>
{
((CollapsibleColumnDefinition)d).IsExpanded = (bool)v;
return v;
}));
我短暂地尝试手动强制刷新依赖项属性(请注意bug),但是CoerceValueCallback确实可以实现我想要的并且更干净。