我有一个包含2个数据的类:
public class Settings
{
EnumType Mode;
float Rate;
}
属性Rate
的值取决于属性Mode
的值。
我使用CoerceValue函数进行更新,确保Rate值始终正确。
该属性以只读模式(单向)绑定到UI,因为我想在写入时执行一些额外的过程。 所以我在UI控件上创建了一个事件,以了解Rate属性何时更改。
在我的窗口中,UI绑定到静态变量SelectedSettings
。
我的问题如下:
当我更改SelectedSettings的值(使用其他设置类)时,它不会在UI中加载新设置,而是执行以下操作:
Mode
值SelectedSettings
。Rate
值(现在不正确)。我做错了什么?我对依赖属性和强制系统的使用是否无效?
修改: 这里有关于我的实际状态的更多信息
我创建了一个用户控件来显示两个设置选项
public partial class EncodingQualitySliderControl : UserControl
{
public static readonly DependencyProperty BitrateProperty = DependencyProperty.Register(
"Bitrate",
typeof(double),
typeof(EncodingQualitySliderControl),
new FrameworkPropertyMetadata(new PropertyChangedCallback(EncodingQualitySliderControl.OnBitrateValueChanged), new CoerceValueCallback(EncodingQualitySliderControl.CoerceBitrateValue)));
public static readonly DependencyProperty EncodingModeProperty = DependencyProperty.Register(
"EncodingMode",
typeof(EncodingMode),
typeof(EncodingQualitySliderControl),
new PropertyMetadata(new PropertyChangedCallback(EncodingQualitySliderControl.OnEncodingModeValueChanged)));
public event EventHandler<double> BitrateValueChanged;
public EncodingQualitySliderControl()
{
this.InitializeComponent();
this.CoerceValue(EncodingQualitySliderControl.BitrateProperty);
Debug.Assert(this.slider != null);
this.slider.ValueChanged += this.Slider_ValueChanged;
}
public EncodingMode EncodingMode
{
get
{
return (EncodingMode)this.GetValue(EncodingQualitySliderControl.EncodingModeProperty);
}
set
{
this.SetCurrentValue(EncodingQualitySliderControl.EncodingModeProperty, value);
}
}
public double Bitrate
{
get
{
return (double)this.GetValue(EncodingQualitySliderControl.BitrateProperty);
}
set
{
this.SetCurrentValue(EncodingQualitySliderControl.BitrateProperty, this.GetNearestTickValue(value));
}
}
private static void OnBitrateValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs eventArgs)
{
EncodingQualitySliderControl encodingQualitySliderControl = sender as EncodingQualitySliderControl;
encodingQualitySliderControl.slider.Value = (double)eventArgs.NewValue;
}
private static object CoerceBitrateValue(DependencyObject sender, object basevalue)
{
EncodingQualitySliderControl encodingQualitySliderControl = sender as EncodingQualitySliderControl;
return encodingQualitySliderControl.GetNearestTickValue((double)basevalue);
}
private static void OnEncodingModeValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs eventArgs)
{
EncodingQualitySliderControl encodingQualitySliderControl = sender as EncodingQualitySliderControl;
Slider sliderControl = encodingQualitySliderControl.slider;
// ... Some code that change the user control depending on the new mode.
encodingQualitySliderControl.CoerceValue(EncodingQualitySliderControl.BitrateProperty);
// Send ValueChanged in case of bitrate value change from coerce value.
encodingQualitySliderControl.BitrateValueChanged?.Invoke(encodingQualitySliderControl, encodingQualitySliderControl.Bitrate);
}
private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
this.SetCurrentValue(EncodingQualitySliderControl.BitrateProperty, e.NewValue);
// Only send the bitrate value changed event if the value change come from the slider.
this.BitrateValueChanged?.Invoke(this, e.NewValue);
}
}
然后我有一个包含我的设置数据的课程:
public class ConversionPreset : INotifyPropertyChanged
{
private EncodingMode mode;
private double bitrate;
public event PropertyChangedEventHandler PropertyChanged;
[XmlAttribute]
public EncodingMode Mode
{
get
{
return this.mode;
}
set
{
this.mode = value;
this.OnPropertyChanged();
}
}
[XmlAttribute]
public double Bitrate
{
get
{
return this.bitrate;
}
set
{
this.bitrate= value;
this.OnPropertyChanged();
}
}
}
然后我的设置类和用户控件之间有数据绑定。
<controls:EncodingQualitySliderControl x:Name="EncodingQualitySlider" BitrateValueChanged="EncodingQualitySlider_ValueChanged"
EncodingMode="{Binding SelectedPreset.Mode, ElementName=window, Mode=OneWay}"
Bitrate="{Binding SelectedPreset.Bitrate, ElementName=window, Mode=OneWay}" />
主窗口中的一些代码可以应用修改
private void EncodingQualitySlider_ValueChanged(object sender, double bitrateValue)
{
this.SelectedPreset?.Bitrate = bitrateValue;
}
编辑2 :
这是一个重现我的问题的最小项目: Linked dependency property test project
想要的行为是:当我启动应用程序时,我想看到preset1(比特率32)。然后,如果我检查预设2,我想看到比特率值为225。
非常感谢。
答案 0 :(得分:0)
由于示例项目,我终于找到了如何让我的项目工作。
我没有完全理解依赖属性的概念,并试图使用控件触发的事件来避免它。
我只是从事件中删除了设置我的设置值的所有代码,然后将属性绑定放在模式&#34; TwoWay&#34;中。我首先没有这样做,因为我不知道如何直接从绑定设置我的设置。为了使它工作,我使用(像Peter Duniho说,谢谢!)值转换器(IValueConverter)。
谢谢大家的意见!