WPF/MVVM/Prism中菜单按钮的实现

WPF/MVVM/Prism中菜单按钮的实现,wpf,mvvm,prism,datatemplate,Wpf,Mvvm,Prism,Datatemplate,我在WPF应用程序的左上角有一个区域,我希望它是我的全局按钮栏,用户可以在这里选择要查看的屏幕,然后在主区域中显示相应的内容。右上角还有一个子导航区域,该屏幕内有子菜单选项,例如,如果用户从主菜单单击维护,子菜单将显示新建、更新、删除、编辑等选项 我想要的是一种创建自定义菜单栏的方法,只需指定一个文本按钮名称列表,以及按钮单击时要调用的操作的ICommand/参数对。实现这一点的自然方法是使用带有依赖属性Title、Command和CommandParameter的MenuButtonViewM

我在WPF应用程序的左上角有一个区域,我希望它是我的全局按钮栏,用户可以在这里选择要查看的屏幕,然后在主区域中显示相应的内容。右上角还有一个子导航区域,该屏幕内有子菜单选项,例如,如果用户从主菜单单击维护,子菜单将显示新建、更新、删除、编辑等选项

我想要的是一种创建自定义菜单栏的方法,只需指定一个文本按钮名称列表,以及按钮单击时要调用的操作的ICommand/参数对。实现这一点的自然方法是使用带有依赖属性Title、Command和CommandParameter的MenuButtonViewModel类。另外还需要一个按钮,IsSelected,因此用户可以通过某种视觉方式查看您当前所在的屏幕,因此它需要像切换按钮一样工作,但一次只能选择组中的一个按钮。然后我可以拥有一个UserControl,其中条的内容绑定到ObservableCollection,并使用数据模板呈现按钮条

到目前为止,我已经尝试了几种方法,但无法找到一种方法来提供我想要的视觉行为。这是我的要求

1个按钮,用于在鼠标悬停时将背景更改为其他画笔 2当选择按钮时,不同的笔刷将显示为背景,直到选择组中的新按钮,如togglebutton IsSelected行为 3一次只能选择组中的一个按钮

到目前为止,我尝试的方法是

1使用我自己的类扩展RadioButton,为command和commandparameter添加依赖属性。将所有控件设置为具有相同的组Id。数据模板覆盖单选按钮的显示,使其看起来像一个带有鼠标悬停和isselected触发器的可视按钮

除了一件事之外,这很好用。选择组中的单选按钮后,无法取消选择单选按钮组中的所有选项。因此,如果您导航到维护,然后单击国家/地区的子菜单(例如),则会显示国家/地区维护屏幕。然后,如果您转到应用程序的另一个区域并从主菜单中选择交易输入,您将进入交易输入屏幕。如果随后单击“维护”,它将显示一般维护内容并返回维护子菜单控件,其中在单选按钮组中选择了国家,但这是不需要的。当您导航回维护时,应取消选择所有子菜单选项,显示通用维护登录页内容,并允许您在显示该屏幕内容之前选择子菜单选项。第一次加载维护时,未选择任何内容,但一旦选择了一个选项,则在重新加载维护屏幕时无法再次选择任何内容

2然后我尝试扩展一个ListBox,用一个水平的stackpanel为内容设置样式,每个listboxitem都是一个menubuttonViewModel。这允许我一次只选择一个选项,并在您离开页面时清除所选内容。它还允许我在将鼠标移到每个listboxitem上时更改背景

我无法使用listbox的一点是在IsSelected触发器上使用不同的背景。在默认的ListBoxItem模板上似乎有一些触发器覆盖了您在CSS中指定的任何内容,因此无论我在ListBoxItem或menubuttonviewmodel样式上放置了什么触发器,背景都不会改变。我认为我需要重新定义listboxitem的数据和内容模板,但只将其应用于此listbox,因此它不能对所有listboxitems进行全局模板更改,因为我希望能够在应用程序中的其他位置使用listbox,而不继承此行为


是否有人能给出他们对这两种方法的想法,以及如何解决我必须使其中一种方法以我想要的方式工作的问题,特别是如果您能建议我如何以我的样式覆盖listboxitems的内容/数据模板,以便它们不使用默认触发器,我可以让IsSelected触发器为我工作吗?

如果我理解正确,每次从另一个主菜单选项返回时,您都希望清除子菜单中单选按钮上的选择

为了解决这个问题,您可以通过手动将RadioButton的IsChecked属性值设置为false来取消选中每个单选按钮。一个可能的解决办法是:

如果每次导航到主菜单的不同部分时都要清除子菜单中的任何选中选项,则可以在选择并单击SelectionChangedEventH中的其他主菜单按钮后,通过使用EventAggregator发布事件,首先通知子菜单的ViewModel 主菜单视图模型的Andrer方法

因此,发布事件的子菜单EventHandler会将每个RadioButton的IsChecked属性值更新为false,这可以通过在视图上定义的每个IsChecked属性和在ViewModel上实现的每个boolean RadioButton1IsChecked属性之间使用双向绑定来实现


我希望这对您有所帮助。

请注意,此解决方案将适用于您提到的第一种方法,它似乎更为优雅,为了正常运行,它只需要一个细节。