将控件的属性绑定到变量,将变量绑定到另一个控件

时间:2014-03-18 19:00:15

标签: wpf binding

很难理解Title中的内容,但我也很难解释,但我会尝试。

我有自定义控件来挑选颜色 自定义控件的Property名为SelectedColor:

/// <summary>
/// SelectedColor property backing ReadOnly DependencyProperty.
/// </summary>
private static readonly DependencyPropertyKey SelectedColorPropertyKey
    = DependencyProperty.RegisterReadOnly("SelectedColor", typeof(Color), typeof(ImageColorPicker)
    , new FrameworkPropertyMetadata(Colors.Transparent
        , FrameworkPropertyMetadataOptions.AffectsRender));
/// <summary>
/// Gets or sets the color selected.
/// </summary>
/// <value>The color selected.</value>
public Color SelectedColor
{
    get { return (Color)GetValue(SelectedColorPropertyKey.DependencyProperty); }
}

我想将Property绑定到我ViewModel中名为TabColor的变量:

public event PropertyChangedEventHandler PropertyChanged; //Event to notify when Property changed.

/// <summary>
/// Notify that Property has Changed.
/// </summary>
/// <param name="propertyName">The name of the Property</param>
protected void NotifyPropertyChanged(string propertyName)
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
} 

private Brush _tabColor; //Color of the Tab.

//Return/Set the color of the Tab.
public Brush TabColor
{ 
    get
    {
        return _tabColor;
    }
    set
    {
        _tabColor = value;
        NotifyPropertyChanged("TabColor");
    }
}

现在,我想将TabColor绑定到我的Style上的Properties:

<Style TargetType="{x:Type MetroStyle:MetroTabItem}">
    <Setter Property="OverridesDefaultStyle" Value="True" />
    <Setter Property="FocusVisualStyle" Value="{x:Null}" />
    <Setter Property="Header" Value="{Binding TabTitle}" />
    <Setter Property="Foreground" Value="{Binding TabColor}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type MetroStyle:MetroTabItem}">
                <Grid Height="26" Background="{TemplateBinding Background}">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="Auto" />
                    </Grid.ColumnDefinitions>
                    <ContentPresenter Margin="5,0" HorizontalAlignment="Left" VerticalAlignment="Center" ContentSource="Header">
                        <ContentPresenter.Resources>
                            <Style TargetType="TextBlock">
                                <Setter Property="Foreground" Value="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type MetroStyle:MetroTabItem}}}" />
                                <Setter Property="HorizontalAlignment" Value="Center" />
                                <Setter Property="VerticalAlignment" Value="Center" />
                            </Style>
                        </ContentPresenter.Resources>
                    </ContentPresenter>
                    <StackPanel Grid.Column="1" Height="16" Margin="0,0,1,0" HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Horizontal">
                        <Button Width="16" Click="ShowHide_Click" Content="&#x1f315;" Style="{StaticResource CustomizedMetroTabItemButton}" ToolTip="Hide" Visibility="{Binding WindowsVisible, Converter={StaticResource BooleanToVisibilityConverter}}" />
                        <Button Width="16" Click="ShowHide_Click" Content="&#x1f311;" Style="{StaticResource CustomizedMetroTabItemButton}" ToolTip="Show" Visibility="{Binding WindowsVisible, Converter={StaticResource InverseBooleanToVisibilityConverter}}" />
                        <Button Width="16" Click="Clear_Click" Content="&#xE107;" Style="{StaticResource CustomizedMetroTabItemButton}" ToolTip="Clear" />
                        <ToggleButton Width="16" x:Name="Edit" Content="&#xE104;" Style="{StaticResource CustomizedMetroTabItemToggleButton}" ToolTip="Edit" />
                        <Popup IsOpen="{Binding IsChecked, Mode=TwoWay, ElementName=Edit}" StaysOpen="False" PlacementTarget="{Binding ElementName=Edit}" Placement="Left" VerticalOffset="{Binding ActualHeight, ElementName=Edit}" HorizontalOffset="{Binding Width, ElementName=Edit}" PopupAnimation="Slide">
                            <StackPanel>
                                <local:ImageColorPicker x:Name="ColorPicker" Source="Images/ColorWheel.png" HorizontalAlignment="Center" Width="100" Height="100"/>
                            </StackPanel>
                        </Popup>
                    </StackPanel>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsSelected" Value="False">
                        <Setter Property="Background" Value="#EFEFF2" />
                    </Trigger>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="#FFFFFF" />
                        <Setter Property="Foreground" Value="{Binding TabColor}" />
                    </Trigger>
                    <Trigger Property="IsSelected" Value="True">
                        <Setter Property="Background" Value="{Binding TabColor}" />
                        <Setter Property="Foreground" Value="#FFFFFF" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

我将变量用作“连接器”的原因是因为我无法将属性绑定到树之外 - 对吧? (我的意思是我不能这样做:<Setter Property="Foreground" Value="{Binding ElementName=ColorPicker, Path=SelectedColor, Converter={StaticResource ColorToBrushConverter}}" />

我还有一张图片可以简化我的要求: binding

如果你有另一种解决方案,只要我能达到我的需要 - 我会接受 谢谢!

修改
我有一个转换器,从Color转换为SolidColorBrush,但我仍然不知道如何进行我想要的绑定:

[ValueConversion(typeof(Color), typeof(Brush))]
public class ColorToBrushConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        Color color = (Color)value;
        return new SolidColorBrush(color);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

EDIT2:
Sample code with everything above

EDIT3:
一张新照片(也许会更容易理解) enter image description here

1 个答案:

答案 0 :(得分:1)

我相信您需要做的就是在Selected Color上设置一个绑定,例如:

<local:ImageColorPicker x:Name="ColorPicker" Source="Images/ColorWheel.png" HorizontalAlignment="Center" Width="100" Height="100" SelectedColor="{Binding Path=TabColor, Converter={StaticResource ColorToBrushConverter}}/>

您始终可以在依赖项属性上设置绑定(但不能设置任何其他内容)。希望这可以清除“树外绑定属性”。如果没有,请澄清你不理解的内容,我很乐意尝试解决它。​​

此外,依赖属性未设置我习惯的方式,所以如果您仍然遇到麻烦,可以考虑使用dpprop代码段设置它,或者按照例如MSDN

<强>评论

绑定有多种模式,如果您只想要一种模式,则只需设置模式变量。在您的情况下,您将绑定更改为:

SelectedColor="{Binding Path=TabColor, Converter={StaticResource ColorToBrushConverter, Mode=OneWay}}

这样,对“TabColor”属性的任何更改都不会传播到ColorPicker,但ColorPicker的更改将设置“TabColor”属性。作为参考,其他模式是:TwoWay(默认),OneTime(在初始化时获得默认值)和OneWayToSource(如OneWay,但它只更改源,并且永远不会获取更新)。

当我提到“异常”依赖属性时,我指的是“SelectedColor”DP的样式。当然TabColor不会是DP :)。

最后,我相信你可以按照描述绑定Value属性。你试过吗?绑定的唯一限制是它必须在DP上完成。

<强>更新

我无法让ColorPicker更新视图模型。我读过的所有内容都表明它应该能够,但我无法弄明白。如果这是一个重要的要求,我建议从头开始,让它正常工作,然后继续。

话虽如此,我确实得到了更新的颜色。尝试将您的XAML更改为:

<TabItem Header="Test" Foreground="{Binding ElementName=ColorPicker, Path=SelectedColor, Converter={StaticResource ColorToBrushConverter}, Mode=OneWay}">
    <Grid>
       <local:ImageColorPicker x:Name="ColorPicker" Source="ColorWheel.png" HorizontalAlignment="Center"/>
    </Grid>
</TabItem>

出于某种原因,我不得不重建几次才能完成这项工作。再说一遍,我很抱歉我原来的请求无法正常工作。

更新2

显然,您需要做的就是将“BindsTwoWayByDefault”添加到元数据选项中。这将导致调用“ConvertBack”函数,因为您正在更新ViewModel。

除了ImageColorPicker之外,你可能可以在所有控件上使用“OneWay”绑定,这样它们就不会意外地设置颜色,但一般来说TwoWay应该没问题。