【问题标题】:WPF binding on Slider does not update on Maximum change滑块上的 WPF 绑定不会在最大更改时更新
【发布时间】:2011-03-19 03:12:59
【问题描述】:
  • combobox1.SelectedItem 绑定到 SelectedItemProperty
  • 设置SelectedItemProperty时,计算MaxValueProperty
  • MaxValueProperty 绑定到slider1.Maximum

  • slider1.Value 绑定到SliderValueProperty

这些都可以正常工作,除非combobox1.SelectedItem 发生变化,并且MaxValueProperty 被计算出来,并且小于SliderValueProperty

在视图中:

  • slider1.Maximum 已更新,因为 MaxValueProperty 已更改,
  • slider1.Value 设置为 slider1.Maximum,这是当最大值更改为小于该值时滑块的默认行为。

但是,发生这种情况时,SliderValueProperty 不会更新为新的slider1.Value

<Slider Name="slider1" Maximum="{Binding Path=MaxValueProperty, Mode=TwoWay}" Value="{Binding Path=SliderValueProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

我知道 slider1.Value 正在发生变化,因为我绑定了一个标签,并且标签发生了变化

<Label Content="{Binding ElementName=slider, Path=Value, Converter={StaticResource NumberToStringConverter}}" />

如何确保绑定已更新?

【问题讨论】:

    标签: wpf data-binding mvvm


    【解决方案1】:

    与其依赖滑块的默认行为和 TwoWay 绑定,不如在 SelectedItemProperty setter 中计算新的最大值后引发 PropertyChanged 事件,首先在“SliderValueProperty " 使用新的最大值,然后是 "MaxValueProperty"。在您的私有支持字段上进行计算,而不是在公共属性上。

    这将导致系统首先调整滑块的值,然后调整最大值,它应该为您移动滑块的位置。

    将slider1的Maximum的绑定模式也设置为OneWay;我认为这会奏效。

    如下图所示:

    Class viewmodel
        Implements INotifyPropertyChanged
    Private _selectedItemProperty As ComboBoxItem
    Public Property SelectedItemProperty As ComboBoxItem
    
        Get
            Return _selectedItemProperty
        End Get
        Set(value As ComboBoxItem)
            MaxValueProperty = value.Content
            If _sliderValueProperty > _maxValueProperty Then _sliderValueProperty = _maxValueProperty
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("MaxValueProperty"))
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("SliderValueProperty"))
        End Set
    End Property
    Private _maxValueProperty, _sliderValueProperty as Single
    Public Property MaxValueProperty As Single ' with setter that will raise PropertyChanged and use the backing field
    
    '...
    
    Public Property SliderValueProperty As Single ' with a setter that will raise PropertyChanged and use the backing field
    
    '...
    
    End Class
    

    XAML 看起来有点像这样:

        <Grid>
        <ComboBox Height="23" HorizontalAlignment="Left" Margin="40,38,0,0" Name="ComboBox1" VerticalAlignment="Top" Width="120" SelectedItem="{Binding SelectedItemProperty}">
            <ComboBoxItem Content="50" />
            <ComboBoxItem Content="30" />
            <ComboBoxItem Content="10" />
        </ComboBox>
        <Slider Name="slider1" Height="23" HorizontalAlignment="Left" Margin="87,135,0,0"  VerticalAlignment="Top" Width="100" Value="{Binding SliderValueProperty}" Minimum="1" Maximum="{Binding MaxValueProperty}" />
        <Label Content="{Binding ElementName=slider1, Path=Value}" Margin="40,174,293,96" />
    
    </Grid>
    

    【讨论】:

    • 在你回答之前不久,我做了一个与你类似的 if 语句,但在属性上,分配 SliderValueProperty 引发它的 propertychanged 事件,解决了我的问题。但是有一个问题 - 为什么要在私有支持字段上进行计算,然后手动引发属性更改事件?
    • 鉴于您对问题的描述,这似乎是使用 MVVM 时最明确和最直接的方法。您有一个属性设置器,它更改了其他属性的条件,虽然您可以按照您选择的方式毫无问题地进行操作,但我对您的程序一无所知。当我希望更改出现在 UI 中时,我通常会选择明确提出 PropertyChanged。
    • 是的,这只是 if(SliderValueProperty &gt; MaxValueProperty){SliderValueProperty = MaxValueProperty; }if(_SliderValueProperty &gt; _MaxValueProperty){_SliderValueProperty = _MaxValueProperty; RaisePropertyChanged(SliderValueProperty);} 之间的区别
    猜你喜欢
    • 2015-11-10
    • 2023-03-28
    • 1970-01-01
    • 2011-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-20
    • 1970-01-01
    相关资源
    最近更新 更多