我有一個包含2數據的類:具有依賴於WPF中另一個屬性值的依賴屬性值是否正確?
public class Settings
{
EnumType Mode;
float Rate;
}
屬性Rate
取決於屬性Mode
的值的值。 我使用CoerceValue函數來更新,確保Rate值始終保持正確。
該屬性以只讀模式綁定到UI(單向),因爲我想在寫入時執行一些額外的過程。 因此,我在我的UI控件上創建了一個事件,以瞭解Rate屬性何時更改。
在我的窗口中,UI綁定到一個靜態變量SelectedSettings
。
我的問題是這樣的:
當我改變SelectedSettings的值(與其他設置類),而不是在用戶界面加載新的設置,將執行以下操作:
- 在UI中設置新的
Mode
值 - 上一個操作將啓動coerceValue過程並修改速率值。
- 速率值的修改觸發事件。
- 觸發事件在
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)。然後,如果我檢查preset2,我想看到一個225的比特率值。
非常感謝。
你必須顯示更多的代碼,顯示視圖,你如何設置datacontext等。似乎你missunderstud依賴屬性的概念,在WPF依賴屬性是用於UI控件。我認爲你的意思是一個'INotifyProperty'改變的對象,所以如果你希望你的對象在屬性改變時更新視圖,你的視圖模型必須實現這個接口。 –
謝謝!我編輯了我的帖子以添加更多關於我的問題的信息。 – Tichau
從你的問題中不清楚實際的預期行爲是什麼。當你說_「屬性值的值取決於屬性模式的值」時,你的意思是說,隨處可見的費率值應該根據模式而變化?或者您想要向用戶呈現不同的價值,同時保持基礎費率值相同?如果是後者,那麼可能你不想強迫,而是使用'IMultiValueConverter'和'MultiBinding'來將模式和速率的輸入組合成正確的UI呈現。 –