4

ユーザー コントロールとカスタム コントロールを追加した wpf アプリケーションを作成しました。カスタム コントロールは、ユーザー コントロール内で使用されます (他の多くの種類のユーザー コントロールで使用される予定です)。

簡単な例として、カスタム コントロールには backgroundcolour という名前のタイプの依存関係プロパティがありBrushます。これは、カスタム コントロールの既定のテンプレートで境界線の背景として設定されます。CommandおよびCommandParameterプロパティを使用して、ユーザー コントロールからこの値を設定できると考えていました。以下でやろうとしたように

ユーザー コントロール 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

わかりました 数日間の検索の後、私は満足しているものを手に入れました。他の誰かが同様の要件を持っている場合に備えて、ここに追加するだけだと思いました。私が直面していた主な問題は、「routedcommand」の完全な無知 (それが単語であれば) でした。コマンドと routedevents は知っていましたが、routedcommand の種類は知りませんでした。また、必要に応じて再度追加できると確信していますが、ユーザーコントロール内のカスタムコントロールのアイデアを削除しました。とにかく、私が現在使用しているコードはこちらです。

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>

CommandParameter によって決定されるいくつかの異なる依存関係のプロパティを変更するために routedcommand が使用されていることがわかると思います。これはおそらく多くの人にとって明らかなことですが、私はこれを接続するのに本当に苦労しました(おそらく私は愚かです)。害がなければ、誰かを助けるかもしれません。

于 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 に答える