WPF-在项目更改时重新绘制上下文菜单?
我在ScrollViewer中有一个ItemsControl,当项目超过ScrollViewer的宽度时,它们会被放入ContextMenu,并显示为下拉菜单。我的问题是,当第一次加载上下文菜单时,它会保存菜单的大小,并且在添加/删除更多命令时不会重新绘制 例如,面板有3个命令。1可见,2在菜单中。查看菜单将显示这两个命令并绘制控件,但如果调整面板的大小,使其显示2个命令,并且菜单中只有1个命令,则不会重新绘制菜单以删除第二个菜单项。甚至更糟糕的是,如果缩小面板,使其不显示任何命令,并且所有3个都在菜单中,则它将只显示前2个 这是我的密码:WPF-在项目更改时重新绘制上下文菜单?,wpf,dynamic,refresh,contextmenu,redraw,Wpf,Dynamic,Refresh,Contextmenu,Redraw,我在ScrollViewer中有一个ItemsControl,当项目超过ScrollViewer的宽度时,它们会被放入ContextMenu,并显示为下拉菜单。我的问题是,当第一次加载上下文菜单时,它会保存菜单的大小,并且在添加/删除更多命令时不会重新绘制 例如,面板有3个命令。1可见,2在菜单中。查看菜单将显示这两个命令并绘制控件,但如果调整面板的大小,使其显示2个命令,并且菜单中只有1个命令,则不会重新绘制菜单以删除第二个菜单项。甚至更糟糕的是,如果缩小面板,使其不显示任何命令,并且所有3个
<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>
我曾尝试使用InvalidateVisual并在渲染时传递一个空委托,以尝试强制重画,但两者都不起作用。我正在使用.Net 4.0。菜单命令是一个集合吗?如果是,它是一个可观察的集合吗
如果将集合绑定到ItemsControl,则该集合必须实现INotifyCollectionChanged接口,以便ItemsControl知道集合中的项数已更改,以便控件可以“重绘”本身。只是好奇为什么要取消ContextMenuOpen事件?这是因为您只希望它显示在左键单击或其他什么?是的,我想在按钮单击时显示菜单,而不是鼠标右键单击确定,但我没有看到任何更改菜单命令集合的代码!代码的哪一部分会更改它?ScrollViewer.SizeChanged事件会根据对象是否在ScrollViewer视口中修改MenuCommand集合并更改IsVisible属性。。。hrrm修改ObservableCollection中的项目可能不会触发ObservableCollection更改事件?没错!为什么不重置集合,只添加每次滚动查看器大小更改或类似更改时需要显示在菜单中的项目?我使用集合作为两个控件—滚动查看器显示可见命令,上下文菜单显示隐藏命令。我不想创建两个集合。你知道我怎么强迫它重新绑定到目标上吗?我尝试使用cMenu.BindingExpression(MenuItem.ItemsSourceProperty).UpdateTarget(),但它没有改变任何内容。将ItemsSource属性设置为null,然后再次将其与集合一起分配如何?或者创建一个从ObservableCollection继承的自定义集合,在其中公开一个引发CollectionChanged事件的公共方法,并调用该方法来更新绑定。
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;
}
}