简体   繁体   English

设置绑定的DependencyProperty时,自定义控件ContextMenu ItemSource不会更新

[英]Custom Control ContextMenu ItemSource doesn't update when bound DependencyProperty is set

I have created a custom control with a style. 我创建了具有样式的自定义控件。 Everything is working fine but the ContextMenu I'm trying to add doesn't show any items. 一切工作正常,但是我要添加的ContextMenu没有显示任何项目。

ButtonAnalysisControl (Custom Control) ButtonAnalysisControl(自定义控件)

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

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    public Brush BackgroundBrush
    {
        get { return (Brush)GetValue(BackgroundBrushProperty); }
        set { SetValue(BackgroundBrushProperty, value); }
    }

    public ObservableCollection<ViewCommand> ChildCommands
    {
        get { return (ObservableCollection<ViewCommand>)GetValue(ChildCommandsProperty); }
        set { SetValue(ChildCommandsProperty, value); }
    }

    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text", typeof(string), typeof(ButtonAnalysisControl), new UIPropertyMetadata(string.Empty));

    public static readonly DependencyProperty BackgroundBrushProperty =
        DependencyProperty.Register("BackgroundBrush", typeof(Brush), typeof(ButtonAnalysisControl), new UIPropertyMetadata(Brushes.Transparent));

    public static readonly DependencyProperty ChildCommandsProperty =
        DependencyProperty.Register("ChildCommands", typeof(ObservableCollection<ViewCommand>), typeof(ButtonAnalysisControl), new UIPropertyMetadata(null));

}

Generic.xaml (ButtonAnalysisControl style) Generic.xaml(ButtonAnalysisControl样式)

<Style TargetType="anal:ButtonAnalysisControl">

    <Style.Triggers>
        <EventTrigger RoutedEvent="MouseDown">
            <EventTrigger.Actions>
                <BeginStoryboard>
                    <Storyboard>
                        <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="ContextMenu.IsOpen">
                            <DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True"/>
                        </BooleanAnimationUsingKeyFrames>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger.Actions>
        </EventTrigger>
    </Style.Triggers>

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="anal:ButtonAnalysisControl">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="*"/>
                    </Grid.RowDefinitions>

                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>

                    <TextBlock TextAlignment="Center"
                               VerticalAlignment="Stretch" 
                               Foreground="{StaticResource CommandBarForeground}" 
                               Background="{StaticResource MainForegroundBrush}"
                               FontFamily="{StaticResource FontFamily}"
                               FontSize="10"
                               Grid.Column="0" 
                               Grid.Row="0">
                        <TextBlock.Text>
                            <Binding Path="Text" StringFormat="{}{0}%" RelativeSource="{RelativeSource TemplatedParent}" />
                        </TextBlock.Text>                            
                    </TextBlock>
                    <Rectangle Grid.Column="0" 
                               Grid.Row="1">
                        <Rectangle.Fill>
                            <Binding Path="BackgroundBrush" RelativeSource="{RelativeSource TemplatedParent}" />
                        </Rectangle.Fill>
                    </Rectangle>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>

    <Setter Property="ContextMenu">
        <Setter.Value>
            <ContextMenu>
                <ContextMenu.ItemsSource>
                    <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="ChildCommands"/>
                </ContextMenu.ItemsSource>
                <ContextMenu.ItemContainerStyle>
                    <Style TargetType="{x:Type MenuItem}">
                        <Setter Property="MenuItem.Header" Value="{Binding Command.Text}"/>
                    </Style>
                </ContextMenu.ItemContainerStyle>
            </ContextMenu>
        </Setter.Value>
    </Setter>
</Style>

ButtonAnalysisControls are created at runtime and they are set as the content of an adorner (this happens in the constructor of the adorner). ButtonAnalysisControls在运行时创建,并将它们设置为装饰器的内容(这发生在装饰器的构造函数中)。 Relevant code: 相关代码:

public ButtonAnalysisAdorner(UIElement adornedElement, int numberOfTimesFieldFilled, int numberOfLoggedViews, ObservableCollection<ViewCommand> childCommands)
        : base(adornedElement)
    {
        _visuals = new VisualCollection(this);
        _contentPresenter = new ContentPresenter();
        ButtonAnalysisControl bac = new ButtonAnalysisControl();
        bac.Text = percentage.ToString(CultureInfo.InvariantCulture);
        bac.BackgroundBrush = PercentColorRanges.GetColorFromPercentage((int)percentage, 0.75);
        bac.ToolTip = ToolTipValue(numberOfTimesFieldFilled, numberOfLoggedViews);
        bac.ChildCommands = childCommands;
        Content = bac;

        _visuals.Add(_contentPresenter);
    }

I inspected ButtonAnalysisControl with Snoop. 我用Snoop检查了ButtonAnalysisControl。 ChildCommands doesn't always have items. ChildCommands并不总是具有项目。 But I looked at a ButtonAnalysisControl from which I know it has ChildCommands. 但是我看了一个ButtonAnalysisControl,从中我知道它具有ChildCommands。 I saw that the ChildCommands dependency property had a collection with two items and ButtonAnalysisControl.ContextMenu.Items had value: 0. I don't know why the contextmenu doesn't have any items, I want the contextmenu to be bound with ChildCommands. 我看到ChildCommands依赖项属性有一个包含两个项目的集合,而ButtonAnalysisControl.ContextMenu.Items的值是:0。我不知道为什么contextmenu没有任何项目,我希望contextmenu与ChildCommands绑定。 How to fix this? 如何解决这个问题?

I don't think the Templated Parent binding will work like you want it to. 我认为Templated Parent绑定不会像您希望的那样工作。 The ContextMenu definition isn't in a template. ContextMenu定义不是一个模板。

You could try something like this: 您可以尝试这样的事情:

<Style TargetType="anal:ButtonAnalysisControl">
    ...    
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="anal:ButtonAnalysisControl">
                <Grid Background="Transparent" Tag="{Binding ChildCommands,RelativeSource={RelativeSource TemplatedParent}}">
                    <Grid.ContextMenu>
                        <ContextMenu ItemsSource="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
    ...

A couple of notes here: 这里有几点注意事项:

  • Any popup breaks the DataContext inheritance, that's why we're going through the Tag property 任何弹出窗口都会破坏DataContext继承,这就是为什么我们要通过Tag属性
  • the grids background is transparent so it will handle clicks 网格背景是透明的,因此可以处理点击
  • you will probably have to rearrange your MouseDown trigger as well to be in the template 您可能还需要重新安排MouseDown触发器才能进入模板
  • 'anal'-namespace?? 'anal'-namespace?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM