【问题标题】:Binding a control to multiple properties in WPF将控件绑定到 WPF 中的多个属性
【发布时间】:2015-09-22 14:35:48
【问题描述】:

首先,如果这个问题很愚蠢,我表示歉意,但我是 WPF 新手,并且在某些控件方面遇到了一些困难。

我有一个图像编辑器应用程序,该应用程序有几个图像微调控件,例如反转、旋转、缩放、亮度和对比度。

要编辑控件,用户选择他们想要编辑的控件,例如亮度,然后一个滑块会出现在图像的一侧(否则会隐藏)。

此滑块当前直接绑定到我的 ViewModel 中的一个属性以获取亮度。

我希望能够重用此 Slider 控件但动态设置绑定,例如当我选择 Zoom 控件时,相同的滑块将更改 Zoom 等等。

我是否应该使用某种空属性,它是指向另一个属性的指针,可以在需要时换出?

我不熟悉 WPF,但我确信有一种更整洁的方式来排序。

任何帮助将不胜感激。

目前我的样子是这样的。

XMAL 滑块控件

<Slider Grid.Row="0" IsSelectionRangeEnabled="True"  SelectionStart="50" SelectionEnd="150" Grid.Column="1" Orientation="Vertical" Minimum="0" Maximum="200" Value="{Binding Brightness}" Visibility="{Binding IsBrightnessAndContrastEnabled, Converter={StaticResource VisibilityConverter}}">

IsBrightnessAndContrastEnabled 是一个简单的布尔值来决定是否显示滑块,

private int _brightness = 100;
    public int Brightness
    {
        get {  return _brightness;}
        set
        {
            if (_brightness != value)
            {
                Set(() => Brightness, ref _brightness, value);
                ChangeBrightnessAndContrastCommand.Execute(null);
            }
        }
    }

【问题讨论】:

  • 是的,我自己也在考虑这个选项,我会选择那个,我认为这可能是一个更容易的选择,但似乎不是。谢谢

标签: c# wpf xaml data-binding


【解决方案1】:

首先,我同意 Silvermind 最好将它放在不同的滑块中。但是要回答您的问题,是的,您要求的是可能的。您只需要两个属性的单个滑块。最好的方法是通过创建负责更改亮度、对比度的第三个属性来执行视图模型中的逻辑。让我把这个属性称为值:

public int Value
{
    get
    {
        return _value; 
    }
    set
    {
        if (_value != value)
        {
            Set(() => Value, ref _value, value);
            ApplyChanges(_value);
        }                
    }
}

每次值改变时,它都会调用 ApplyChanges 方法,这将根据选择的控件更新您的亮度或对比度。

void ApplyChanges(int value)
{       
    if(_selectedControl.Equals("brightness") && this.Brightness != value)
        this.Brigtness = value; 
    else if(_selectedControl.Equals("contrast") && this.Contrast != value)
        this.Contras = value; 
}

您说过用户会选择他们喜欢使用的控件。所以选中的控件本身是我们需要跟踪的另一个属性。您需要知道在您的视图模型中选择了哪个控件,以便您知道在值更改时应该更新哪个(亮度/对比度)。在我的示例中,为简单起见,我将只使用一个字符串,这将告诉视图模型选择了哪个。

public string SelectedControl
{
    get {  return _selectedControl;}
    set
    {
        if (_selectedControl != value)
        {
            Set(() => Contrast, ref _selectedControl, value);
            if(_selectedControl.Equals("brightness"))
                this.Value = this.Brightness;
            else if(_selectedControl.Equals("contrast"))
                this.Value = this.Contrast;
        }
    }
}

每次选定控件发生变化时,如果用户选择另一个控件,我们将更新 Value 属性并传递当前选定控件的值。当用户将对比度设置为 3,然后将亮度设置为 20,然后再次选择对比度时,滑块值应该回到 3 或对比度的值。每次所选控件更改时,滑块中的值也会更新。

最后,您需要将属性 Value 绑定到 Slider 的值。

【讨论】:

    【解决方案2】:

    我会使用多个滑块,但为它们创建一个包含所有共享属性的单独样式。这可以减少您的代码并使其更易于阅读/维护。

    <Style x:Key="MySliderStyle" TargetType="{x:Type Slider}">
        <Setter Property="IsSelectionRangeEnabled" Value="True" />
        <Setter Property="SelectionStart" Value="0" />
        <Setter Property="SelectionEnd" Value="150" />
        <Setter Property="Orientation" Value="Vertical" />
        <Setter Property="Minimum" Value="0" />
        <Setter Property="Maximum" Value="200" />
    </Style>
    
    <Slider Style="{DynamicResource MySliderStyle}" Grid.Row="0" Grid.Column="1" 
            Value="{Binding Brightness}" Visibility="{Binding IsBrightnessAndContrastEnabled, Converter={StaticResource VisibilityConverter}}">
    

    如果您真的想使用相同的滑块,您可以动态更改分配给 Slider 控件的样式,并让不同的样式定义绑定和可见性值应该是什么。

    <Style x:Key="BrightnessSlider" TargetType="{x:Type Slider}" BasedOn="{DynamicResource MySliderStyle}">
        <Setter Property="Value" Value="{Binding Brightness}" />
        <Setter Property="Visibility" Value="{Binding IsBrightnessAndContrastEnabled, Converter={StaticResource VisibilityConverter}}" />
    </Style>
    
    <Slider x:Name="MySingleSlider" Grid.Row="0" Grid.Column="1">
    

    不知何故在后面的代码中或在切换滑块的用途时使用的任何内容:

    MySingleSlider.Style = this.FindResource("BrightnessSlider") as Style;
    

    您还可以将这两种方法结合起来并创建 #2 中定义的样式,但在 XAML 中使用单独的滑块,如 #1 中一样。然后您的 XAML 会更简单,您可以自定义每个滑块的属性,使其具有各自的样式。

    <Slider Style="{DynamicResource BrightnessSlider}" Grid.Row="0" Grid.Column="1">
    

    (您也可以将Grid.RowGrid.Column 属性放在&lt;Style&gt; 中,但通常它们与您布局控件的方式相关联,因此我更喜欢将这些属性保留在控件上)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-13
      • 1970-01-01
      • 2011-12-05
      相关资源
      最近更新 更多