WPF - 当项目更改时重绘上下文菜单?

发布于 2024-09-05 08:19:59 字数 2164 浏览 3 评论 0原文

我在 ScrollViewer 中有一个 ItemsControl,当项目超过 ScrollViewer 的宽度时,它们会被放入 ContextMenu 中并显示为 DropDown。我的问题是,当首次加载上下文菜单时,它会保存菜单的大小,并且在添加/删除更多命令时不会重绘。

例如,一个面板有 3 个命令。 1 可见,2 在菜单中。查看菜单会显示 2 个命令并绘制控件,但如果您调整面板大小,使 2 个命令可见并且菜单中只有 1 个命令,则它不会重新绘制菜单以消除第二个菜单项。或者更糟糕的是,如果您缩小面板以便不显示任何命令并且所有 3 个命令都在菜单中,则它只会显示前 2 个命令。

https://i193.photobucket.com/albums/z197/Lady53461/ContextMenuRedraw.jpg

这是我的代码:

<Button Click="DropDownMenu_Click"
        ContextMenuOpening="DropDownMenu_ContextMenuOpening">

    <Button.ContextMenu>
        <ContextMenu ItemsSource="{Binding Path=MenuCommands}" Placement="Bottom">
            <ContextMenu.Resources>
                <Style TargetType="{x:Type MenuItem}">
                    <Setter Property="Command" Value="{Binding Path=Command}" />
                    <Setter Property="Visibility" Value="{Binding Path=IsVisible, Converter={StaticResource ReverseBooleanToVisibilityConverter}}"/>
                </Style>
            </ContextMenu.Resources>
            <ContextMenu.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Path=DisplayName}" />
                </DataTemplate>
            </ContextMenu.ItemTemplate>
        </ContextMenu>
    </Button.ContextMenu>
</Button>

代码隐藏:

        void DropDownMenu_ContextMenuOpening(object sender, ContextMenuEventArgs e)
    {
        Button b = sender as Button;
        b.ContextMenu.IsOpen = false;
        e.Handled = true;
    }

    private void DropDownMenu_Click(object sender, RoutedEventArgs e)
    {
        Button b = sender as Button;

        ContextMenu cMenu = b.ContextMenu;
        if (cMenu != null)
        {
            cMenu.PlacementTarget = b;
            cMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.Bottom;
            cMenu.IsOpen = true;
        }
    }

我尝试使用 InvalidateVisual 并在渲染上传递一个空委托尝试强制重绘,但都不起作用。我正在使用.Net 4.0。

I have a ItemsControl in a ScrollViewer, and when the items exceed the width of the ScrollViewer they are put into a ContextMenu and shown as a DropDown instead. My problem is that when the Context Menu is first loaded, it saves the saves the size of the Menu and does not redraw when more commands get added/removed.

For example, a panel has 3 commands. 1 is visible and 2 are in the Menu. Viewing the menu shows the 2 commands and draws the control, but then if you resize the panel so 2 are visible and only 1 command is in the menu, it doesn't redraw the menu to eliminate that second menu item. Or even worse, if you shrink the panel so that no commands are shown and all 3 are in the Menu, it will only show the top 2.

https://i193.photobucket.com/albums/z197/Lady53461/ContextMenuRedraw.jpg

Here's my code:

<Button Click="DropDownMenu_Click"
        ContextMenuOpening="DropDownMenu_ContextMenuOpening">

    <Button.ContextMenu>
        <ContextMenu ItemsSource="{Binding Path=MenuCommands}" Placement="Bottom">
            <ContextMenu.Resources>
                <Style TargetType="{x:Type MenuItem}">
                    <Setter Property="Command" Value="{Binding Path=Command}" />
                    <Setter Property="Visibility" Value="{Binding Path=IsVisible, Converter={StaticResource ReverseBooleanToVisibilityConverter}}"/>
                </Style>
            </ContextMenu.Resources>
            <ContextMenu.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Path=DisplayName}" />
                </DataTemplate>
            </ContextMenu.ItemTemplate>
        </ContextMenu>
    </Button.ContextMenu>
</Button>

Code Behind:

        void DropDownMenu_ContextMenuOpening(object sender, ContextMenuEventArgs e)
    {
        Button b = sender as Button;
        b.ContextMenu.IsOpen = false;
        e.Handled = true;
    }

    private void DropDownMenu_Click(object sender, RoutedEventArgs e)
    {
        Button b = sender as Button;

        ContextMenu cMenu = b.ContextMenu;
        if (cMenu != null)
        {
            cMenu.PlacementTarget = b;
            cMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.Bottom;
            cMenu.IsOpen = true;
        }
    }

I have tried using InvalidateVisual and passing an empty delegate on Render to try and force a redraw, however neither works. I'm using .Net 4.0.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

赠我空喜 2024-09-12 08:19:59

MenuCommands 是一个集合吗?如果是,它是一个 ObservableCollection 吗?

如果将集合绑定到 ItemsControl,则该集合必须实现 INotifyCollectionChanged 接口,以让 ItemsControl 知道集合中的项目数已更改。更改,以便控件可以“重绘”自身。

Is MenuCommands a collection? If it is, is it an ObservableCollection?

If you bind a collection to an ItemsControl, that collection must implement INotifyCollectionChanged interface to let the ItemsControl know that the number of items in the collection has changed, so that the control can "redraw" itself.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文