I think it’s one of the most common scenarios around, you would like to bind a button set for use of typical operations.
See those 3 little buttons next to the title? It’s a very common case, having 3 generic buttons for CRUD operations over data right next to datagrid for ease of use. It can be whatever and you could effectively put there a few more, but this will suffice for showing off a nice way how caliburn.micro can make your life easier.
So for instance you have this control with these generic buttons, and you called it ListButtons:
<UserControl x:Class="AltinetSilver.AltiControls.ListButtons" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:telerik="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls" mc:Ignorable="d" VerticalAlignment="Bottom" Margin="5,0,5,0"> <UserControl.Resources> <SolidColorBrush x:Key="BorderBrush" Color="#FF767676" /> </UserControl.Resources> <StackPanel Orientation="Horizontal" Grid.Column="1" HorizontalAlignment="Right"> <Button x:Name="Add" BorderBrush="Transparent" BorderThickness="0,0,0,0" Visibility="{Binding AddNewButtonVisibility}" Height="18" Margin="2,4,2,4" Width="18"/> <Button x:Name="Edit" BorderBrush="Transparent" BorderThickness="0,0,0,0" Visibility="{Binding EditButtonVisibility}" Height="18" Margin="2,4,2,4" Width="18"/> <Button x:Name="Delete" BorderBrush="Transparent" BorderThickness="0,0,0,0" Visibility="{Binding DeleteButtonVisibility}" Height="18" Margin="2,4,4,4" Width="19" Padding="0"/> </StackPanel> </UserControl>
U use it in your PartnersView.xaml in the following way
. . <StackPanel Orientation="Horizontal"> <TextBlock Style="{StaticResource HeaderStyle}" VerticalAlignment="Top" Text="{Binding Partners,Source={StaticResource Strings}}"/> <AltiControls:ListButtons x:Name="PartnerButtons"/> </StackPanel> . .
It’s the code shown from the picture above, buttons next to the header. Notice the name of the control, it’s important for the convention
Your PartnersViewModel.cs looks something like this, with commands for using those buttons:
. . public void AddPartner() { } public bool CanAddPartner { get { return true; }} public void DeletePartner() { } public bool CanDeletePartner { get { return SelectedPartner != null; } } public void EditPartner() { } public bool CanEditPartner { get { return SelectedPartner != null; } } . .
So you want to hook up these methods to those generic buttons without any extra work.
First let’s define how a convention would look like
ConventionManager.AddElementConvention<ListButtons>(UserControl.ContentProperty, "DataContext", null) .ApplyBinding = (viewModelType, path, property, element, convention) => { var buttons = element as ListButtons; if (buttons == null) return; if (!buttons.Name.EndsWith("Buttons")) return; var entName = buttons.Name.Remove(buttons.Name.IndexOf("Buttons")); SetListButton(viewModelType, buttons.Add, "Add" + entName); SetListButton(viewModelType, buttons.Edit, "Edit" + entName); SetListButton(viewModelType, buttons.Delete, "Delete" + entName); };
What we are doing here is searching for naming convention for ListButtons class. It has to start with entity name and end with “Buttons” text. After we find it, we go through buttons and Set them up.
SetListButton function looks like following:
private static void SetListButton(Type modelType,AltiButton button,string methodName) { if (modelType.GetMethod(methodName) != null) Message.SetAttach(button, methodName); else button.Visibility = Visibility.Collapsed; }
So there you have it. This method basically hooks up a button with an appropriate methodname, or it hides the button.
One last thing left to do. We need to define a property in the main viewmodel so we expose the object which holds our button methods. For the previous example, you just add the following to PartnersViewModel.cs
public object PartnerButtons { get { return this; } }
Caliburn will hook the property to “PartnerButtons” user control, and the convention will do the rest. Hope this helps!
Leave a Comment