将控件绑定到WPF中的多个属性

时间:2015-09-22 14:35:48

标签: c# wpf xaml data-binding

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

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

要编辑控件,用户可以选择他们想要编辑的控件,例如亮度,并在图像的一侧显示滑块(否则会隐藏)。

此滑块当前直接绑定到我的ViewModel for Brightness中的属性。

我希望能够重复使用这个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是一个简单的bool决定是否显示滑块,

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

2 个答案:

答案 0 :(得分:1)

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

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

每次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的值。

答案 1 :(得分:1)

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

<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,并让不同的样式定义Binding和Visibility值应该是什么。

<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属性放在<Style>中,但通常情况下它们会与您的控件相关联,所以我更愿意保留控件上的那些属性