Breaking entity framework Entity reference link - c#

This is probably a newbie question but I’m breaking my head about this one.
I’m building an application in WPF using the MVVM pattern. I have a view which has fields binded a property exposing the current customer entity. And within the view I have a command to change the bank account numbers belonging to that customer. The command called take the whole sub-entity as parameter. Then call another function which also takes the sub-entity as parameter and passes it to a new viewmodel binded to a new view which is displayd as a dialog for change. This all works. But when I’m change the bank account number in the dialog the original view also changes the account number number real-time. They are still connected to each other. I want to cancel this link to be able to cancel the dialog and the changes I made within that dialog. But I can’t get this to work.
Code say’s more the words.
View MAIN
<dxlc:LayoutGroup Header="Rekeningen" View="GroupBox" Orientation="Vertical" VerticalAlignment="Stretch">
<dxlc:LayoutItem>
<StackPanel>
<Button Content="{x:Static language:Common.NieuwRekeningnrToevoegen}" Command="{Binding NieuwRekeningCommand}" />
<ListView ItemsSource="{Binding CurrentRelatie.Rekeningnummers}" ItemTemplate="{StaticResource RelatieRekeningnrTemplate}" />
</StackPanel>
</dxlc:LayoutItem>
</dxlc:LayoutGroup>
View item template MAIN
<DataTemplate x:Key="RelatieRekeningnrTemplate">
<Grid>
<TextBlock >
<Run Text="{Binding Omschrijving}" FontWeight="Bold" FontStyle="Italic" /> <LineBreak/>
<Run Text="{Binding RekNummer}" /> - <Run Text="{Binding BicNummer}" FontStyle="Italic" />
</TextBlock>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top">
<Button Command="{Binding DataContext.VerwijderRekeningCommand, RelativeSource={RelativeSource AncestorType=UserControl}}" CommandParameter="{Binding}">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="BorderBrush" Value="{x:Null}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Template" Value="{DynamicResource tplFlatButton}" />
</Style>
</Button.Style>
<Path Height="9" Stretch="Uniform" Fill="{DynamicResource AccentColorDarkGray}" Data="{DynamicResource Delete}" />
</Button>
<Button Command="{Binding DataContext.EditRekeningCommand, RelativeSource={RelativeSource AncestorType=UserControl}}" CommandParameter="{Binding}">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="BorderBrush" Value="{x:Null}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Template" Value="{DynamicResource tplFlatButton}" />
</Style>
</Button.Style>
<Path Height="10" Stretch="Uniform" Fill="{DynamicResource AccentColorDarkGray}" Data="{DynamicResource Edit}" >
</Path>
</Button>
</StackPanel>
</Grid>
</DataTemplate>
Viewmodel
private model.Relatie _CurrentRelatie = null;
public model.Relatie CurrentRelatie
{
get { return _CurrentRelatie; }
set { SetProperty(ref _CurrentRelatie, value, () => CurrentRelatie); }
}
public ICommand EditRekeningCommand { get; private set; }
void OnEditRekeningExecute(model.Rekeningnummer Rek)
{
EditRekeningnummer(Rek);
}
private void EditRekeningnummer(model.Rekeningnummer Rek)
{
Dialog.dRekeningnummerEditViewModel ReknummerVM = new Dialog.dRekeningnummerEditViewModel();
ReknummerVM.SetRekening(Rek);
UICommand ResCommand = DialogService.ShowDialog(ReknummerVM.DialogUICommand, string.Format("{0} {1}", Common.Rekening, Rek.Omschrijving ?? Rek.RekNummer), "viewdRekeningnummerEdit", ReknummerVM);
if (ResCommand == null || ResCommand.IsCancel == true)
return;
}
View RekeningnummerEdit
<dxlc:LayoutGroup Orientation="Vertical">
<dxlc:LayoutItem Label="{Binding CurrentRekening, ConverterParameter=Omschrijving, Converter={StaticResource ModelToDisplay}}">
<dxe:TextEdit EditValue="{Binding CurrentRekening.Omschrijving, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" ValidateOnTextInput="True" utils:FocusAdvancement.AdvancesByEnterKey="true"/>
</dxlc:LayoutItem>
<dxlc:LayoutItem Label="{Binding CurrentRekening, ConverterParameter=RekNummer, Converter={StaticResource ModelToDisplay}}">
<dxe:TextEdit EditValue="{Binding CurrentRekening.RekNummer, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" ValidateOnTextInput="True" utils:FocusAdvancement.AdvancesByEnterKey="true"/>
</dxlc:LayoutItem>
<dxlc:LayoutItem Label="{Binding CurrentRekening, ConverterParameter=BicNummer, Converter={StaticResource ModelToDisplay}}">
<dxe:TextEdit EditValue="{Binding CurrentRekening.BicNummer, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" ValidateOnTextInput="True" utils:FocusAdvancement.AdvancesByEnterKey="true"/>
</dxlc:LayoutItem>
</dxlc:LayoutGroup>
Viewmodel RekeningnummerEdit
public dRekeningnummerEditViewModel()
{
DialogUICommand = new List<UICommand>();
AnnuleerUICommand = new UICommand() {
Caption=Common.Annuleren,
Id = MessageBoxResult.Cancel,
IsCancel=true
};
OKUICommand = new UICommand() {
Caption=Common.Opslaan,
Id = MessageBoxResult.OK,
IsDefault=true
};
DialogUICommand.Add(OKUICommand);
DialogUICommand.Add(AnnuleerUICommand);
CurrentRekening = new model.Rekeningnummer();
}
public void SetRekening(model.Rekeningnummer Rek)
{
CurrentRekening = Rek;
IsInEditMode = true;
}
#region "Properties"
private model.Rekeningnummer _CurrentRekening;
public model.Rekeningnummer CurrentRekening
{
get { return _CurrentRekening; }
set { SetProperty(ref _CurrentRekening, value, () => CurrentRekening); }
}
#endregion
#region "Private function"
#endregion
#region "Commands"
public List<UICommand> DialogUICommand { get; private set; }
protected UICommand AnnuleerUICommand { get; private set; }
protected UICommand OKUICommand { get; private set; }

The behaviour you're seeing is because you are passing an object reference (model.Rek) from your view to your dialog. Therefore when your dialog changes the values of the model.Rek, the changes are immediately reflected in your view.
A common approach to solve this problem is to:
Clone (copy) your model, i.e. make a new object with the same values. You can use the ICloneable interface as a standard pattern (MemberwiseClone can help here if you only need a shallow copy)
Send the clone to your dialog
If the user presses OK, then take the values of the clone and copy them back to the original model. If the user presses Cancel, then do nothing more

Related

Problem with ActivateItem by the ContextMenu on DataGrid using CaliburnMicro

I am using caliburn micro on my project. So far I have had no problems with ActivateItemAsync. Now, however, this method does not activate my ActiveItem. Now what my code looks like:
I have a DashboardMainView:
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Ribbon ...>
</Ribbon>
<Grid Grid.Row="1" Background="#E8E8E8">
<ContentControl x:Name="ActiveItem" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
</ContentControl>
</Grid>
Then in DashboardMainViewModel:
public class DashboardMainViewModel : Conductor<object>
{
private IDialogCoordinator dialogCoordinator;
public DashboardMainViewModel(IDialogCoordinator instance)
{
this.dialogCoordinator = instance;
ActivateItemAsync(new DashboardSummaryViewModel());
}
public async Task Execution()
{
await ActivateItemAsync(new BasicExecutionViewModel(DialogCoordinator.Instance));
}
So far everything works, but then BasicExecutionView is activated, where I have a DataGrid and MenuContext in it. And here comes the problem, when we right-click on the DataGrid, a menu pops up where, after selecting an interesting option, it should activate another view ... but it does not. My code looks like this:
<Grid >
<Viewbox Stretch="Fill">
<DataGrid
x:Name="BasicExecutionGrid"
CanUserSortColumns="True"
IsReadOnly="True"
CanUserAddRows="False"
FontSize="11"
Height ="800"
ScrollViewer.CanContentScroll="True"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Auto" AutoGeneratingColumn="BasicExecutionGrid_AutoGeneratingColumn">
<DataGrid.ColumnHeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock TextWrapping="Wrap"
Text="{Binding}"
HorizontalAlignment="Center"
VerticalAlignment="Center"></TextBlock>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="Background" Value="LightSteelBlue"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Height" Value="45"/>
</Style>
</DataGrid.ColumnHeaderStyle>
<DataGrid.ContextMenu>
<ContextMenu>
<MenuItem Header="Details"
Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}, Path=DataContext.ActivateCellDetailsView}"
>
</MenuItem>
</ContextMenu>
</DataGrid.ContextMenu>
</DataGrid>
</Viewbox>
</Grid>
In BasicExecutionViewModel I have:
class BasicExecutionViewModel : Conductor<object>
{
private IDialogCoordinator dialogCoordinator;
private RelayCommand activateCellDetailsView { get; set; }
public BasicExecutionViewModel(IDialogCoordinator instance)
{
this.dialogCoordinator = instance;
}
public ICommand ActivateCellDetailsView
{
get
{
if (activateCellDetailsView == null)
{
activateCellDetailsView = new RelayCommand(async p=> await ActivateCellView());
}
return activateCellDetailsView;
}
}
public async Task ActivateCellView()
{
await ActivateItemAsync(new CellDetailsExecutionViewModel());
}
}
The code comes to ActivateCellView () and activates it. I can see it in Output Window where ActiveItem takes the value of the CellDetailsExecutionViewModel () object, but BasicExecutionView is still displayed on the screen. What am I doing wrong? I guess it's something with either DataContext or parent-child issue ... please help :)
PS. I'm not a professional programmer I'm a hobbyist.
Solved
I solved the problem. My mistake was using Conductor<object> incorrectly. In DashboardMainViewModel. When I corrected on
DashboardMainViewModel: Conductor<object>.Collection.OneActive
ant the same in the BasicExecutionViewModel
BasicExecutionViewModel: Conductor<object>.Collection.OneActive
I also updated the code in the ActivateCellView() method to
public async Task ActivateCellView()
{
CellDetailsExecutionViewModel cellDetailsExecutionViewAcvtivate = new CellDetailsExecutionViewModel();
var parentConductor = (Conductor<object>.Collection.OneActive)(this.Parent);
await parentConductor.ActivateItemAsync(cellDetailsExecutionViewAcvtivate);
}
And everything works beautifully

Bound TabControl Repeats Same Content Or Controls Across Tabs

In the example below when data is bound to the tab control, it correctly has the tab headers per the data, but the tab content is always the same; and the last item bound to.
"Frank Wright"'s "Wright" is on every page.
What is wrong? One expects that there are different controls on every page, not one control shared or data repeated.
<Page.Resources>
<model:People x:Key="People">
<model:Person First="Joe"
Last="Smith"
Phone="303-555-5555" />
<model:Person First="Jenny"
Last="Johnson"
Phone="720-867-5309" />
<model:Person First="Frank"
Last="Wright"
Phone="202-555-5555" />
</model:People>
</Page.Resources>
<TabControl ItemsSource="{StaticResource People}">
<TabControl.ItemContainerStyle>
<Style TargetType="TabItem">
<Setter Property="Header"
Value="{Binding First}" />
<Setter Property="Content">
<Setter.Value>
<TextBox Text="{Binding Last}" />
</Setter.Value>
</Setter>
</Style>
</TabControl.ItemContainerStyle>
</TabControl>
public class People : List<Person> { }
public class Person
{
public string First { get; set; }
public string Last { get; set; }
public string Phone { get; set; }
}
You want to set the ContentTemplate, not the Content:
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBox Text="{Binding Last}" />
<Label Content="{Binding Phone}" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>

C# WPF Combobox editable only allow option from list

I have a combobox with names in it. I have the box set to editable so that the user can enter a name. I want it so that the user can only enter a name that is already in the list.
When the user clicks save I want the box to have the red validation border show up if the box is empty or not in the list.
Is there a way to do this?
<ComboBox IsEditable="True"
Grid.Column="2"
Grid.Row="1"
Margin="5,3,0,0"
Text="{Binding Model.Number}"
ItemsSource="{Binding DList}"
SelectedItem="{Binding Model.Number}"
IsEnabled="{Binding EnableComboBox}"
VerticalAlignment="Top">
</ComboBox>
If I understood correctly, you want the user to be able to select an existing list item by typing, but not type a string that is not on the list. That can be done with the following:
<ComboBox IsEditable="False"></ComboBox>
This will allow the user to start typing the string, but you lose the textbox for input.
Another way to do it is to allow the user to type whatever they want by setting <ComboBox IsReadOnly="False" IsEditable="True"> and handle for example the LostFocus event to check if the input is valid. Here's an example:
private void ComboBox_LostFocus(object sender, RoutedEventArgs e)
{
bool allowed = false;
foreach (ComboBoxItem it in comboBox.Items)
{
if (it.Content.ToString() == comboBox.Text)
{
allowed = true;
break;
}
}
if (!allowed)
{
MessageBox.Show("MISS!");
}
else
{
MessageBox.Show("HIT!");
}
}
For some reason I wasn't able to set the border color quickly, but you get the point from here. Also depending on your ComboBoxItem type, you may need to match the comboBox.Text to a certain property.
Let's assume you use MVVM (it's not what you're doing now) and that
ItemsSource="{Binding DList}"
is a correct binding to a collection of Models
You'd need a
DisplayMemberPath="Number"
Back to your question.
First, let's write another binding for the selected Text
Text="{Binding Selected, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors =true, NotifyOnValidationError=true}"
and implement the validation tooltip inside the combo
ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"
and the style in the window resources
<Window.Resources>
<Style TargetType="{x:Type Label}">
<Setter Property="Margin" Value="5,0,5,0" />
<Setter Property="HorizontalAlignment" Value="Right" />
</Style>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="0,2,40,2" />
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="true">
<Border Background="Red" DockPanel.Dock="right" Margin="5,0,0,0" Width="20" Height="20" CornerRadius="10"
ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
<TextBlock Text="!" VerticalAlignment="center" HorizontalAlignment="center" FontWeight="Bold" Foreground="white">
</TextBlock>
</Border>
<AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" >
<Border BorderBrush="red" BorderThickness="1" />
</AdornedElementPlaceholder>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
Finally, we've to validate the ViewModel property
We can project the model list to its numbers for the error check
public class VM : IDataErrorInfo
{
public string this[string columnName]
{
get
{
if (columnName.Equals( "Selected"))
{
if (!DList.Select(m => m.Number).Contains(Selected))
return "Selected number must be in the combo list";
}
return null;
}
}
You can learn more about data validation in MVVM for example here
Fire the validation later
Say you want fire the validation after a save button is clicked
<Button Content="Save"
Command="{Binding SaveCmd}"
you simply need to raise the property changed in the corresponding delegate command
public class VM : ViewModelBase, IDataErrorInfo
{
private bool showValidation;
private int selected;
public int Selected
{
get { return selected; }
set
{
selected = value;
showValidation = true;
OnPropertyChanged("Selected");
}
}
DelegateCommand saveCmd;
public ICommand SaveCmd
{
get
{
if (saveCmd == null)
{
saveCmd = new DelegateCommand(_ => RunSaveCmd(), _ => CanSaveCmd());
}
return saveCmd;
}
}
private bool CanSaveCmd()
{
return true;
}
private void RunSaveCmd()
{
showValidation = true;
OnPropertyChanged("Selected");
}
and exit from the validation before you want to show it.
public string this[string columnName]
{
get
{
if (!showValidation)
{
return null;
}

Combobox SelectedItem change all binded Textboxes in ListView that have the same bind value

So I have a ComboBox in a UserControl. This UserControl is shown when an item is selected from a ListView and is responsible for editing the values of the selected object. The problem is that if I have in the ListView more objects with the same value that the ComboBox is responsible to change, all of this values are change to the value of the selected item in the ListView.
I have this ListView:
<ListView x:Name="AcorduriListView" ItemsSource="{Binding ., UpdateSourceTrigger=PropertyChanged}"
ItemContainerStyle="{StaticResource AcordListViewItem}" />
With this template:
<Style TargetType="ListViewItem" x:Key="AcordListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Grid
d:DataContext="{d:DesignData Source=DesignTimeData/AcordSampleData.xaml, IsDesignTimeCreatable=True}">
...
<TextBlock x:Name="CategorieDescriptionTextBlock" Padding="3,0,0,0" Foreground="Black"
Visibility="{Binding ElementName=CategorieTextBlock, Path=Text, Converter={StaticResource StringNullOrEmptyToVisibilityConverter}}"
Text="Completează categoria" />
<TextBlock x:Name="CategorieTextBlock"
Padding="3,0,0,0" Foreground="Black"
Text="{Binding Categorie.Nume}"
Visibility="{Binding ElementName=CategorieDescriptionTextBlock, Path=IsVisible, Converter={StaticResource InverteBooleanToVisibilityConverter}}" />
...
</StackPanel>
</Border>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="rootPanel" Property="Background"
Value="{StaticResource AccentColorBrush}" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="rootPanel" Property="Background"
Value="{StaticResource AccentColorBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The ListView is bound to a collection of this Object:
public class Acord : INotifyPropertyChanged, IChangeTracking
{
public string Name{ get; set; }
...
public int CategorieId { get; set; }
public virtual Categorie Categorie { get; set; }
}
where Categorie is:
public class Categorie : INotifyPropertyChanged
{
public string Nume { get; set; }
....
private ObservableCollection<Acord> _acorduri;
public virtual ObservableCollection<Acord> Acorduri{ get; set; }
}
When an item from this ListView is Selected, a UserControl is shown based on a trigger on the ListView SelectedIndex. The UserControl has it's DataContext bind to the ListView SelectedItem (an Acord object). From the many controls in this UserControl I have a Combobox CategorieAcordComboBox that has it's ItemsSource bind to a collection of Categorie objects.
<ComboBox Grid.Row="2" Margin="5,0,5,5" x:Name="CategorieAcordComboBox"
DisplayMemberPath="Nume" SelectedValuePath="CategorieId"
Text="{Binding Categorie.Nume}"
IsSynchronizedWithCurrentItem="False" />
<DatePicker Grid.Row="3" Margin="5" FontSize="16" x:Name="DataAcorDatePicker"
controls:TextBoxHelper.Watermark="Data"
SelectedDate="{Binding Data, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Grid.Row="4" x:Name="LocatieAcordTextBox" Margin="5"
controls:TextBoxHelper.UseFloatingWatermark="True"
controls:TextBoxHelper.Watermark="Locație" FontSize="16"
Text="{Binding Locatie, UpdateSourceTrigger=PropertyChanged}" />
My problem is that when I select a diffrent item in ComboBox, while the Text binding is set to Categorie.Nume the content of all the TextBoxes CategorieTextBlock from the template that have the same value, changes to the selected value from ComboBox.
Video: http://screencast.com/t/bbRsb6RMwkZ7

How can I create elements with trigger invoke method in SilverLight?

This question is a continuation of the pregoing one.( How can I combine some UserControls in SilverLight?)
I have 3 view models with different colour properties.
How can I create elements of User Control with trigger invoke method after pressing the button on the element.
Here is a code of this element that I have upgrade with the trigger action.
<UserControl x:Class="SilverlightApplication14.NodePicture"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:SilverlightApplication14"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
<Grid x:Name="LayoutRootNodePicture" Height="100" Width="100"
HorizontalAlignment="Center">
<Canvas x:Name="ParentCanvas" Background="{Binding NodeColor}" Width="100" Height="100" >
</Canvas>
<Image HorizontalAlignment="Center"
Source="add.png"
Stretch="Fill"
Width="16"
VerticalAlignment="Top"
Margin="0,0,2,2"
Height="16" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<local:Add />
</i:EventTrigger>
</i:Interaction.Triggers>
</Image>
</Grid>
</UserControl>
And the code with the trigger action
namespace SilverlightApplication14
{
public class Add : TriggerAction<FrameworkElement>
{
protected override void Invoke(object parameter)
{
var vm = AssociatedObject.DataContext as NodeViewModel;
if (vm != null)
{
if (vm.Nodes == null)
{
vm.Nodes = new ObservableCollection<NodeViewModel>();
}
var child = new NodeViewModel { NodeColor = new SolidColorBrush(Color.FromArgb(255, 255, 0, 0)) };
vm.Nodes.Add(child);
}
}
}
}
Updated code:
<Grid>
<Grid.Resources>
<Style x:Key="myStyle" TargetType="ListBoxItem">
<Setter Property="Background" Value="Khaki" />
<Setter Property="Foreground" Value="DarkSlateGray" />
<Setter Property="Margin" Value="5" />
<Setter Property="FontStyle" Value="Italic" />
<Setter Property="FontSize" Value="14" />
<Setter Property="BorderBrush" Value="DarkGray" />
</Style>
</Grid.Resources>
<ListBox ItemsSource="{Binding Nodes}" ItemContainerStyle="{StaticResource myStyle}">
<ListBox.ItemTemplate>
<DataTemplate>
<local:NodePicture DataContext="{Binding}" />
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</Grid>
Is there a simple (or a right way ) way of doing this?
It is preferable to work with business-logic in view models, whereas triggers are intended for working with UI.
I would change the trigger to a command:
<Button Command="{Binding AddCommand}">
<Button.Template>
<ControlTemplate TargetType="Button">
<Image ... />
</ControlTemplate>
</Button.Template>
</Button>
When a user clicks the button, the AddCommand is invoked. It can be implemented in the view model so:
public class NodeViewModel
{
public NodeViewModel()
{
this.AddCommand = new RelayCommand(obj => { /* do something */ });
}
public RelayCommand AddCommand { get; private set; }
//...
}
The RelayCommand class is one of the possible implementations and it can be downloaded with the MVVM Light framework here.

Categories

Resources