Activation/deactivation of toolbar buttons using Prism
I’m in the process of learning the Prism framework and I’ve come along way already. But I was wondering about how to create toolbars (and context menus) where each module can register their own buttons.
For this example I want all buttons to reside in the same ToolBar control which is located in my Shell. The ToolBars ItemsSource
binds to a ToolBarItems
property of type ObservableCollection<FrameworkElement>
in the view model. Elements can be added to this collection using a ToolBarRegistry
service. This is the ViewModel:
public class ShellViewModel
{
private IToolBarRegistry _toolBarRegistry;
private ObservableCollection<FrameworkElement> _toolBarItems;
public ShellViewModel()
{
_toolBarItems = new ObservableCollection<FrameworkElement>();
_toolBarRegistry = new ToolBarRegistry(this);
}
public ObservableCollection<FrameworkElement> ToolBarItems
{
get { return _toolBarItems; }
}
}
Note that the collection of type FrameworkElement will be refactored to be of a more concrete type if this turns out to be the correct solution.
My ToolBarRegistry
has a method to register image buttons:
public void RegisterImageButton(string imageSource, ICommand command)
{
var icon = new BitmapImage(new Uri(imageSource));
var img = new Image();
img.Source = icon;
img.Width = 16;
var btn = new Button();
btn.Content = img;
btn.Command = comman开发者_运维知识库d;
_shellViewModel.ToolBarItems.Add(btn);
}
I call this method from my OrderModule
and the buttons show up correctly. So far so good.
The problem is how I can control when these buttons should be removed again. If I navigate to a view in another module (and sometimes another view in the same module), I want these module-specific buttons to be hidden again.
Do you have any suggestions on how to do this? Am I approaching this problem the wrong way, or can I modify what I already have? How did you solve this problem?
I would not insert Button
instances in the ObservableCollection
. Think about this approach instead:
Create ViewModel for the toolbar buttons
class ToolBarButtonViewModel : INotifyPropertyChanged
{
// INotifyPropertyChanged implementation to be provided by you
public string ImageSource { get; set; }
public ICommand Command { get; set; }
public bool IsVisible { get; set; }
}
Then of course change the type of ToolBarItems
to a collection of these.
In your ShellView
, add a DataTemplate
for ToolBarButtonViewModel
and bind the ItemsSource
of whatever your toolbar control is to the collection of ViewModels, for example:
<DataTemplate>
<Button Command="{Binding Command}">
<Button.Content>
<Image Source="{Binding ImageSource}" />
</Button.Content>
</Button>
</DataTemplate>
You can now bind Button.Visibility
to IsVisible
with a BooleanToVisibilityConverter
to solve your immediate problem.
As an added bonus, you can also:
- Change the visual appearance of the toolbar buttons entirely from XAML
- Bind any property of the visual tree for a toolbar button to corresponding properties on the
ToolBarButtonViewModel
Update
The mechanism for enabling/disabling buttons depends on specifics of your application. There are many options -- here are a few (keep this chart in mind while reading):
- Implement
INavigationAware
in your Views or ViewModels and enable/disable buttons as required - Attach handlers to the events of
IRegionNavigationService
of the region(s) of interest and have the handlers enable or disable buttons - Route all navigation through your own code (
CustomNavigationService
) and decide what to do inside it
精彩评论