4

我创建了一个 wpf 应用程序,在其中添加了一个用户控件和一个自定义控件。自定义控件在用户控件中使用(计划在许多其他类型的用户控件中使用)。

举个简单的例子,自定义控件有一个Brush名为 backgroundcolour 类型的依赖属性,然后在自定义控件的默认模板中将其设置为边框的背景。我的想法是,我可以使用CommandandCommandParameter属性从用户控件中设置此值。正如我试图在下面做的那样

用户控件 xaml(TestControl 是自定义控件)

<Grid>
    <Grid.Resources>
        <MyNamespace:EditColourCommand x:Key="EditColour"/>
    </Grid.Resources>

    <Grid.ContextMenu>
        <ContextMenu>
            <MenuItem Name="Test" 
                      Header="Test" 
                      Command="{StaticResource EditColour}" 
                      CommandParameter="{Binding ElementName=testControl1, Path=BackgroundColour, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
        </ContextMenu>
    </Grid.ContextMenu>

    <MyNamespace:TestControl HorizontalAlignment="Left" 
                             Margin="213,90,0,0" 
                             x:Name="testControl1" 
                             VerticalAlignment="Top" 
                             Height="77" 
                             Width="230"/>

</Grid>

我的自定义控制代码背后:

public class TestControl : Control
{
    static TestControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(TestControl), 
            new FrameworkPropertyMetadata(typeof(TestControl)));
    }

    public static DependencyProperty BackgroundColourProperty = 
        DependencyProperty.Register("BackgroundColour", 
                                    typeof(Brush), 
                                    typeof(TestControl), 
                                    new PropertyMetadata(Brushes.Blue, 
                                        BackgroundColourPropertyChangedHandler));

    public Brush BackgroundColour
    {
        get
        {
            return (Brush)GetValue(BackgroundColourProperty);
        }
        set
        {
            SetValue(BackgroundColourProperty, value);
        }
    }

    public static void BackgroundColourPropertyChangedHandler(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
    } 
}

最后,命令

public class EditColourCommand : ICommand
{
    public bool CanExecute(object parameter)
    {
        return true;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        parameter = Brushes.Black;
    }
}

该命令被触发并且在这种情况下它具有默认值蓝色作为参数,但它从不将值设置为黑色。有人可以把我推向正确的方向吗?

4

2 回答 2

1

好的经过几天的搜索,我得到了一些我很满意的东西。我想我会在这里添加它,以防其他人有类似的要求。我面临的主要问题是完全不知道“路由命令”(如果这是一个词),我知道命令和路由事件,但不知道路由命令类型。我也放弃了在用户控件中使用自定义控件的想法,尽管我确信如果我也需要我可以重新添加它。无论如何继承我现在使用的代码。

public class Block : Control
{
    static Block()

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        CommandBindings.Add(new CommandBinding(EditColorCommand, EditColor, CanEditColor));  
    }

    public static readonly DependencyProperty TitleBackgroundColorProperty = DependencyProperty.Register("TitleBackgroundColor", typeof(SolidColorBrush), typeof(Block), new FrameworkPropertyMetadata(Brushes.Gray, null));
    public SolidColorBrush TitleBackgroundColor
    {
        get { return (SolidColorBrush)base.GetValue(TitleBackgroundColorProperty); }
        set { base.SetValue(TitleBackgroundColorProperty, value); }
    }

    public static readonly DependencyProperty TitleLeftTextColorProperty = DependencyProperty.Register("TitleLeftTextColor", typeof(SolidColorBrush), typeof(Block), new FrameworkPropertyMetadata(Brushes.Black, null));
    public SolidColorBrush TitleLeftTextColor
    {
        get { return (SolidColorBrush)base.GetValue(TitleLeftTextColorProperty); }
        set { base.SetValue(TitleLeftTextColorProperty, value); }
    }

    public static readonly DependencyProperty TitleRightTextColorProperty = DependencyProperty.Register("TitleRightTextColor", typeof(SolidColorBrush), typeof(Block), new FrameworkPropertyMetadata(Brushes.Black, null));
    public SolidColorBrush TitleRightTextColor
    {
        get { return (SolidColorBrush)base.GetValue(TitleRightTextColorProperty); }
        set { base.SetValue(TitleRightTextColorProperty, value); }
    }


    public static readonly DependencyProperty BodyBackgroundLowColorProperty = DependencyProperty.Register("BodyBackgroundLowColor", typeof(SolidColorBrush), typeof(Block), new FrameworkPropertyMetadata(Brushes.Gray, null));
    public SolidColorBrush BodyBackgroundLowColor
    {
        get { return (SolidColorBrush)base.GetValue(BodyBackgroundLowColorProperty); }
        set { base.SetValue(BodyBackgroundLowColorProperty, value); }
    }
    public static readonly DependencyProperty BodyBackgroundHighColorProperty = DependencyProperty.Register("BodyBackgroundHighColor", typeof(SolidColorBrush), typeof(Block), new FrameworkPropertyMetadata(Brushes.Gray, null));
    public SolidColorBrush BodyBackgroundHighColor
    {
        get { return (SolidColorBrush)base.GetValue(BodyBackgroundHighColorProperty); }
        set { base.SetValue(BodyBackgroundHighColorProperty, value); }
    }

    public static readonly ICommand EditColorCommand = new RoutedCommand("EditColor", typeof(Block));
    public static void EditColor(Object sender, ExecutedRoutedEventArgs e)
    {
        DependencyProperty dp = e.Parameter as DependencyProperty;
        SolidColorBrush dpVal = ((Block)sender).GetValue(dp) as SolidColorBrush;

        ((Block)sender).SetValue(dp, new SolidColorBrush(Colors.Blue));
    }
    public static void CanEditColor(Object sender, CanExecuteRoutedEventArgs e)
    {
        DependencyProperty dp = e.Parameter as DependencyProperty;

        if (((Block)sender).GetValue(dp).GetType() == typeof(SolidColorBrush))
            e.CanExecute = true;
        else
            e.CanExecute = false;
    }
}

默认模板

<Style TargetType="{x:Type local:Block}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:Block}">
                <Border BorderBrush="Black" BorderThickness="1" CornerRadius="3,3,6,6">
                    <Border.Background>
                        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                            <GradientStop Color="{Binding BodyBackgroundHighColor.Color,  RelativeSource={RelativeSource TemplatedParent}}" Offset="0" />
                            <GradientStop Color="{Binding BodyBackgroundLowColor.Color,  RelativeSource={RelativeSource TemplatedParent}}" Offset="1" />
                        </LinearGradientBrush>
                    </Border.Background>
                    <Grid Name="MainGrid" Background="Transparent">
                        <Grid.Resources>
                            <ContextMenu x:Key="TitleContextMenuKey">
                                <MenuItem Name="EditTitleBackgroundColorCommand" Header="Edit Title Background Color" CommandParameter="{x:Static local:Block.TitleBackgroundColorProperty}" Command="{x:Static local:Block.EditColorCommand}" CommandTarget="{Binding Path=PlacementTarget, RelativeSource={RelativeSource FindAncestor,  AncestorType={x:Type ContextMenu}}}" />
                                <MenuItem Name="EditTitleTextLeftColorCommand" Header="Edit Left Title Text Color" CommandParameter="{x:Static local:Block.TitleLeftTextColorProperty}" Command="{x:Static local:Block.EditColorCommand}" CommandTarget="{Binding Path=PlacementTarget, RelativeSource={RelativeSource FindAncestor,  AncestorType={x:Type ContextMenu}}}" />
                                <MenuItem Name="EditTitleTextRightColorCommand" Header="Edit Right Title Text Color" CommandParameter="{x:Static local:Block.TitleRightTextColorProperty}" Command="{x:Static local:Block.EditColorCommand}" CommandTarget="{Binding Path=PlacementTarget, RelativeSource={RelativeSource FindAncestor,  AncestorType={x:Type ContextMenu}}}" />
                            </ContextMenu>
                            <ContextMenu x:Key="BodyContextMenuKey">
                                <MenuItem Name="EditBodyBackgroundLowColorCommand" Header="Edit Body Low Background Color" CommandParameter="{x:Static local:Block.BodyBackgroundLowColorProperty}" Command="{x:Static local:Block.EditColorCommand}" CommandTarget="{Binding Path=PlacementTarget, RelativeSource={RelativeSource FindAncestor,  AncestorType={x:Type ContextMenu}}}" />
                                <MenuItem Name="EditBodyBackgroundHighColorCommand" Header="Edit Body High Background Color" CommandParameter="{x:Static local:Block.BodyBackgroundHighColorProperty}" Command="{x:Static local:Block.EditColorCommand}" CommandTarget="{Binding Path=PlacementTarget, RelativeSource={RelativeSource FindAncestor,  AncestorType={x:Type ContextMenu}}}" />
                            </ContextMenu>
                        </Grid.Resources>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="30" />
                            <RowDefinition Height="*" MinHeight="50" />
                        </Grid.RowDefinitions>
                        <Viewbox Name="TitleBar" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Stretch="Fill" >
                            <Viewbox.Style>
                                <Style>
                                    <Setter Property="Viewbox.ContextMenu" Value="{StaticResource TitleContextMenuKey}"/>
                                </Style>
                            </Viewbox.Style>
                            <Canvas Name="TitleBarDesign" Width="750" Height="200">
                                <Canvas.Resources>
                                    <LinearGradientBrush xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Key="linearGradient3932" MappingMode="Absolute" StartPoint="376,-69" EndPoint="384,131">
                                        <LinearGradientBrush.GradientStops>
                                            <GradientStopCollection>
                                                <GradientStop Color="#FFFFFFFF" Offset="0"/>
                                                <GradientStop Color="#00FFFFFF" Offset="1"/>
                                            </GradientStopCollection>
                                        </LinearGradientBrush.GradientStops>
                                        <LinearGradientBrush.Transform>
                                            <TranslateTransform X="-0.0625" Y="2.3125"/>
                                        </LinearGradientBrush.Transform>
                                    </LinearGradientBrush>
                                    <LinearGradientBrush xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Key="linearGradient3905" MappingMode="Absolute" StartPoint="372,293" EndPoint="366,111">
                                        <LinearGradientBrush.GradientStops>
                                            <GradientStopCollection>
                                                <GradientStop Color="#FF000000" Offset="0"/>
                                                <GradientStop Color="#00000000" Offset="1"/>
                                            </GradientStopCollection>
                                        </LinearGradientBrush.GradientStops>
                                        <LinearGradientBrush.Transform>
                                            <TranslateTransform X="-0.06249985" Y="2.3124958"/>
                                        </LinearGradientBrush.Transform>
                                    </LinearGradientBrush>
                                </Canvas.Resources>
                                <Canvas Name="TitleBarImagery">
                                    <Canvas.RenderTransform>
                                        <TranslateTransform X="0.0625" Y="-2.3125"/>
                                    </Canvas.RenderTransform>
                                    <Rectangle Name="Color" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="750" Height="200" RadiusX="9.8214264" RadiusY="9.8214264" Fill="{TemplateBinding TitleBackgroundColor}" />
                                    <Rectangle Name="Shadow" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Canvas.Left="0" Canvas.Top="2" Width="750" Height="199" RadiusX="9.8214264" RadiusY="9.8214264" Fill="{StaticResource linearGradient3905}" StrokeThickness="0" Stroke="#FF000000" StrokeMiterLimit="4" StrokeLineJoin="Round" StrokeStartLineCap="Flat" StrokeEndLineCap="Flat"/>
                                    <Path Name="Highlight" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Fill="{StaticResource linearGradient3932}" StrokeThickness="0" Stroke="#FF000000" StrokeMiterLimit="4" StrokeLineJoin="Round" StrokeStartLineCap="Flat" StrokeEndLineCap="Flat">
                                        <Path.Data>
                                            <PathGeometry Figures="m 14.08947 7.4627848 c -5.6134084 0 -10.1232994 6.7033202 -10.1232994 14.9876462 l 0 0.666118 C 86.399783 75.974267 227.79549 110.85376 388.42587 110.85376 c 143.91412 0 272.39283 -28.007413 356.86245 -71.845549 l 0 -16.55778 c 0 -8.284326 -4.50989 -14.9876462 -10.12331 -14.9876462 l -721.07554 0 z" FillRule="NonZero"/>
                                        </Path.Data>
                                    </Path>
                                </Canvas>
                            </Canvas>
                        </Viewbox>
                        <Label Name="lblLeftText" Content="{TemplateBinding TitleLeftText}" Foreground="{TemplateBinding TitleLeftTextColor}" HorizontalAlignment="Left" />
                        <Label Name="lblRightText" Content="{TemplateBinding TitleRightText}" Foreground="{TemplateBinding TitleRightTextColor}" HorizontalAlignment="Right"/>
                        <StackPanel Name="Body"  Grid.Row="1" Background="Transparent">
                            <StackPanel.Style>
                                <Style>
                                    <Setter Property="StackPanel.ContextMenu" Value="{StaticResource BodyContextMenuKey}"/>
                                </style>
                        </StackPanel>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

希望您可以看到 routedcommand 用于更改由 CommandParameter 确定的几个不同的依赖项。这对很多人来说可能是显而易见的,但我真的很痛苦把它挂起来(可能我很笨)。如果没有造成伤害,也许它会帮助某人。

于 2012-06-27T14:07:57.847 回答
0

只需将您的命令修改为

CommandParameter="{Binding ElementName=testControl1}"

并将您的命令执行修改为

public void Execute(object parameter)
{
    var ctrl = parameter as TestControl 
    ctrl.BackgroundColour = Brushes.Black;
}

您不能期望绑定像在 CommandParameter 中那样工作。

于 2012-06-21T19:41:44.173 回答