I am trying to do a basic use of CollectionViewSource and I must be missing something because it is just not working. Here is my XAML:
<Window.Resources>
<CollectionViewSource Source="{Binding loc:MainVM.Instance.MapItems}" x:Key="MapCV">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="SourceProject" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</Window.Resources>
<ListBox ItemsSource="{StaticResource MapCV}" HorizontalContentAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding SourceType, Converter={StaticResource WorkItemTypeToStringConverter}}"/>
<ComboBox Grid.Column="1" SelectedItem="{Binding DestType}" ItemsSource="{Binding WorkItemTypesForCurrentDestProject, Source={x:Static loc:MainMediator.Instance}, diagnostics:PresentationTraceSources.TraceLevel=High}" DisplayMemberPath="Name" />
<Button Grid.Column="2" Content="{Binding PercentMapped}"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
This compiles fine, but when I run the app I get this error:
Cannot convert the value in attribute 'ItemsSource' to object of type
'System.Collections.IEnumerable'. 'System.Windows.Data.CollectionViewSource'
is not a valid value for property 'ItemsSource'. Error at object
'System.Windows.Controls.ListBox' in markup file 'WIAssistant;component/main.xaml
This is the collection I am attaching to:
// The mappings used to copy the values of the fields of one WorkItem to another.
public ObservableCollection<WorkItemTypeMapping> WorkItemTypeMappings
{
get { return (ObservableCollection<WorkItemTypeMapping>)
GetValue(WorkItemTypeMappingsProperty); }
set { SetValue(WorkItemTypeMappingsProperty, value); }
}
public static readonly DependencyProperty WorkItemTypeMappingsProperty =
DependencyProperty.Register("WorkItemTypeMappings",
typeof(ObservableCollection<WorkItemTypeMapping>), typeof(MainMediator),
new UIPropertyMetadata(null));
I just want to do simple grouping on object Project SourceProject. I would rather not have to break out a tree view for this.
This should work for you
<ListBox ItemsSource="{Binding Source={StaticResource MapCV}}" ...
Related
I am working with MVVM design pattern where I want to change the type of control to be used based on the type of item source object.
My code for item source types :
public class PropertyItemVM : ViewModelBase
{
// Some base code for all basic property items
}
public class StringValuePropertyItemVM : PropertyItemVM
{
// Code to correctly create string value property item
}
public class ComboBoxPropertyItemVM : PropertyItemVM
{
// Code to correctly create combo box property item
}
In my view model I have property list binded to xaml as
public ObservableCollection<PropertyItemVM> Properties { get; set; }
This collection contains both the types of objects StringValuePropertyItemVM and ComboBoxPropertyItemVM.
Now what I want to achieve is, based on type of object I want to decide whether the xaml will contain a TextBox or a ComboBox.
My xaml code :
<StackPanel>
<!--Items Control containing all list of properties to be shown-->
<ItemsControl x:Name="Local" ItemsSource="{Binding Properties}" Background="White">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<Label Content="{Binding Label}"
IsEnabled="{Binding IsEnabled}"
Grid.Column="0"/>
<!-- Here based on type need to change the TextBox with ComboBox-->
<TextBox Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Grid.Column="1"
IsEnabled="{Binding IsEnabled}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
With some help I found out I can have different data templates for both types and switch among those, however I can't find how to do that. Can anyone help me with how can this be achieved ?
Automatic Data Template Selection
Move the data templates to the ItemsControl resources and assign a DataType.
<StackPanel>
<!--Items Control containing all list of properties to be shown-->
<ItemsControl x:Name="Local" ItemsSource="{Binding Properties}" Background="White">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type local:StringValuePropertyItemVM}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<Label Content="{Binding Label}"
IsEnabled="{Binding IsEnabled}"
Grid.Column="0"/>
<!-- Here based on type need to change the TextBox with ComboBox-->
<TextBox Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Grid.Column="1"
IsEnabled="{Binding IsEnabled}"/>
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type local:ComboBoxPropertyItemVM}">
<ComboBox/>
</DataTemplate>
</ItemsControl.Resources>
</ItemsControl>
</StackPanel>
The ItemsControl will automatically select the right data template based on the type.
Data Template Selector
Although you do not need it in this case, for more complex cases (e.g. conditions based on the view model), you could implement a DataTemplateSelector, like this:
public class PropertyDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (!(container is FrameworkElement frameworkElement))
return null;
switch (item)
{
case StringValuePropertyItemVM _:
return (DataTemplate)frameworkElement.FindResource("StringValuePropertyItemVMDataTemplate");
case ComboBoxPropertyItemVM _:
return (DataTemplate)frameworkElement.FindResource("ComboBoxPropertyItemVMDataTemplate");
default:
return null;
}
}
}
Then you would define the data templates in a resource dictionary in scope with keys.
<DataTemplate x:Key="StringValuePropertyItemVMDataTemplate" DataType="{x:Type local:StringValuePropertyItemVM}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<Label Content="{Binding Label}"
IsEnabled="{Binding IsEnabled}"
Grid.Column="0"/>
<!-- Here based on type need to change the TextBox with ComboBox-->
<TextBox Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Grid.Column="1"
IsEnabled="{Binding IsEnabled}"/>
</Grid>
</DataTemplate>
<DataTemplate x:Key="ComboBoxPropertyItemVMDataTemplate" DataType="{x:Type local:ComboBoxPropertyItemVM}">
<ComboBox/>
</DataTemplate>
Finally, you would assign or reference an instance of the selector to the ItemsControl.
<StackPanel>
<!--Items Control containing all list of properties to be shown-->
<ItemsControl x:Name="Local" ItemsSource="{Binding Properties}" Background="White">
<ItemsControl.ItemTemplateSelector>
<local:PropertyDataTemplateSelector/>
</ItemsControl.ItemTemplateSelector>
</ItemsControl>
</StackPanel>
I have using the itemscontrol in WPF, I have given the dictionary collection as itemsource for itemscontrol. In this dictionary collection, will be used key and observablecollection. Different items will be in observablecollection of each dictionary items. so, when i'm given an itemsource it will be taken same height.
see the code:
<ItemsControl
Grid.Row="1"
Height="Auto"
ItemsSource="{Binding Values}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
IsItemsHost="True"
Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<GroupBox
MinWidth="303"
Margin="5,0,0,0">
<ItemsControl Margin="20,5,0,5">
<ItemsControl.Resources>
<CollectionViewSource x:Key="Collection" Source="{Binding Value}" />
<DataTemplate DataType="{x:Type Model:Sensor}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label
Grid.Column="1"
Content="{Binding Name}"
FontFamily="SegoeUI-Semibold"
FontSize="12"
FontWeight="SemiBold" />
<Label
Grid.Column="2"
HorizontalContentAlignment="Center"
Content="{Binding Value}"
FontFamily="SegoeUI"
FontSize="12" />
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type Model:DigitalInput}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label
Grid.Column="1"
Content="{Binding Name}"
FontFamily="SegoeUI-Semibold"
FontSize="12"
FontWeight="SemiBold" />
<Label
Grid.Column="2"
HorizontalContentAlignment="Center"
Content="{Binding InputState}"
FontFamily="SegoeUI"
FontSize="12" />
</Grid>
</DataTemplate>
</ItemsControl.Resources>
<ItemsControl.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection="{Binding Source={StaticResource Collection}}" />
</CompositeCollection>
</ItemsControl.ItemsSource>
</ItemsControl>
</GroupBox>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
see the class code:
private Dictionary<string, ObservableCollection<IValue>> values;
public Dictionary<string, ObservableCollection<IValue>> Values
{
get { return values; }
set { values = value; }
}
Current output:
Expected output:
I need to group the items as an expected output, so could you please provide any solution to achieve that?
This is how WrapPanel works. If you set Horizontal all items in row will have same height and it wraps elements to the next row.
You can try specifying Orientation="Vertical" for your WrapPanel, but not quite sure if it suits you. In this case all elements in column will have same width.
Otherwise you don't need either WrapPanel or UniformGrid, you need different panel which is called StaggeredPanel. Source code for uwp can be easily used in WPF, I just checked it.
Only had to rewrite one line which is not a big deal with the following answer: RegisterPropertyChangedCallback(Panel.HorizontalAlignmentProperty, OnHorizontalAlignmentChanged);
An explanation for similar control can be found on codeproject (Called VariableSizedWrapGrid). But I checked it and it has errors somewhere.
On ios it's called mosaic view or StaggeredLayoutManager for RecyclerView on Android.
Instead of WrapPanel, try a UniformGrid:
<UniformGrid Columns="1" IsItemsHost="True" />
Also, I'm not sure about the Height="Auto" setting. Remove it. The setting belongs to the RowDefinition of the grid.
I have a TabControl in my app. I'd like to have as many TabItems as many entries are in my dictionary.
Here's my dictionary:
public Dictionary<string , ObservableCollection<PerformanceCounter>> Counters
{
get { return _Counters; }
}
Dictionary<string, ObservableCollection<PerformanceCounter>> _Counters = new Dictionary<string , ObservableCollection<PerformanceCounter>>();
Every entry has a string key and ObservableCollection of PerformanceCounter objects. Important thing is the fact that every PerformanceCounter object has properties: CounterName and InstanceName - I'll need these two to display them.
Now, to my XAML:
<TabItem Header="Memory">
<Grid Name="RAMGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListBox Name="RAMListBox" Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" ItemsSource="{Binding Memory, Mode=OneWay}" SelectionMode="Multiple" BorderThickness="1" BorderBrush="#FF8B8B8B" SelectionChanged="RAMListBox_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock>
<Run Text="{Binding CounterName, Mode=OneWay}" />
<Run Text="{Binding InstanceName, Mode=OneWay}" />
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Name="RAMSelectAllButton" Margin="0,10,0,0" Grid.Column="0" Grid.Row="1" Click="RAMSelectAllButton_Click" >
<TextBlock Text="SELECT ALL"/>
</Button>
<Button Name="RAMUnSelectAllButton" Margin="0,10,0,0" Grid.Column="1" Grid.Row="1" Click="RAMUnSelectAllButton_Click" >
<TextBlock Text="UNSELECT ALL"/>
</Button>
</Grid>
</TabItem>
That's what I did and, as you might already know, it does not work. The above code is only for one entry of my dictionary, where the key is "Memory".
In my code I set DataContext:
this.DataContext = appData.Counters;
appData.Counters is that dictionary I presented at the beginning.
Here's what I'd like to achieve:
No matter how many entries there are in my dictionary, my TabControl would display TabItem for each of them.
Each TabItem has a ListBox and 2 buttons. I'll need too be able to access those (in order to clear the list and to have click event for each button).
I really don't know how to do it, I hope you can help me out.
Binding TabControl to items in Dictionary:
<Window.Resources>
<DataTemplate x:Key="templateForTheContent" >
<StackPanel>
<ListBox Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0"
ItemsSource="{Binding Value, Mode=OneWay}"
SelectionMode="Multiple"
BorderThickness="1" BorderBrush="#FF8B8B8B">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock>
<Run Text="{Binding CounterName, Mode=OneWay}" />
<Run Text="{Binding InstanceName, Mode=OneWay}" />
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="templateForTheHeader" >
<TextBlock Text="{Binding Key}"/>
</DataTemplate>
</Window.Resources>
<Grid>
<TabControl TabStripPlacement="Left" VerticalAlignment="Stretch" HorizontalContentAlignment="Stretch"
ItemsSource="{Binding Counters}"
ContentTemplate="{StaticResource templateForTheContent}"
ItemTemplate="{StaticResource templateForTheHeader}">
</TabControl>
</Grid>
Now, Dictionary is not observable so if items will be added/removed during runtime, you may consider using something like ObservableDictionary instead
Create a ViewModel-class containing:
your Dictionary
two ICommand-Implementations for your Buttons
then
set the ViewModel-class as DataContext of the TabControl
set Counters as the ItemSource of the TabControl
reuse your XAML-Code defined within the TabItem and use it as
the Tabcontrol.ContentTemplate
Bind .Command of your Buttons to the ICommands in your ViewModel using RelativeSource
see for samples:
ContentTemplate: https://wpf.2000things.com/tag/tabcontrol/
ICommand https://stackoverflow.com/a/1468830/4919708
RelativeSource: https://stackoverflow.com/a/84317/4919708
As i said in one of the comments above I changed my Dictionary to this:
//list of all counters
public ObservableCollection<ObservableCollection<PerformanceCounter>> Counters
{
get { return _Counters; }
}
ObservableCollection<ObservableCollection<PerformanceCounter>> _Counters = new ObservableCollection<ObservableCollection<PerformanceCounter>>();
i used #Arie's solution to write this XAML:
<DataTemplate x:Key="templateForTheContent" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListBox Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0"
ItemsSource="{Binding}"
SelectionMode="Multiple"
BorderThickness="1" BorderBrush="#FF8B8B8B">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock>
<Run Text="{Binding CounterName, Mode=OneWay}" />
<Run Text="{Binding InstanceName, Mode=OneWay}" />
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Name="RAMSelectAllButton" Margin="0,10,0,0" Grid.Column="0" Grid.Row="1" >
<TextBlock Text="SELECT ALL"/>
</Button>
<Button Name="RAMUnSelectAllButton" Margin="0,10,0,0" Grid.Column="1" Grid.Row="1" >
<TextBlock Text="UNSELECT ALL"/>
</Button>
</Grid>
</DataTemplate>
<DataTemplate x:Key="templateForTheHeader" >
<TextBlock Text="{Binding CategoryName}"/>
</DataTemplate>
</Window.Resources>
It displays correctly as many Tabs as I add entries to my Class ObservableCollection in the code behind.
Now i have a new problem: I don't know how to access each listBox from each Tab. i need to be able to read the list of selected objects.
I'm using WPFLocalizationExtension to localize a C#/ .Net4.5 application but I didn't manage to localize DropDown Menus with custom DataTemplate because I can't use the DisplayMemberPath. For ordinary dropdown localization works like this:
<telerik:RadComboBox ItemsSource="{Binding GlassColors}"
SelectedValue="{Binding Ampule.ID_GlassColor, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
SelectedValuePath="ID_GlassColor"
DisplayMemberPath="{lang:Loc dmp_GlassColor}"/>
The ComboBox example above is linked to a database table containing to language. The displayed language is changed by the localized DisplayMemberPath. This approach is very easy and I can recommend it to everyone else. How ever it doesn't work for comboboxes using a custom DataTemplate. See example below:
<telerik:RadComboBox ItemsSource="{Binding PackagingTypesFilter}"
SelectedValue="{Binding SelectedPackagingTypeFilter}"
SelectedValuePath="ID_PackagingType">
<telerik:RadComboBox.ItemTemplate>
<DataTemplate DataType="{x:Type model:Tbl_PackagingMaster_ID_PackagingType}">
<Grid VerticalAlignment="Center" HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Source="{Binding TypeIcon, Converter={StaticResource StringToUriConverter}}" VerticalAlignment="Top" Grid.Column="0" Height="14" Margin="2" />
<TextBlock Text="{Binding PackagingTypeDescription}" Style="{StaticResource TextBlockMediumSmallBlackStyle}" Grid.Column="1"/>
</Grid>
</DataTemplate>
</telerik:RadComboBox.ItemTemplate>
</telerik:RadComboBox>
The ItemSource is a Collection where PackagingTypeDescription contains the English and PackagingTypeDescriptionGerman contains the German description.
How can I localize the code sample above?
I solved this using a TemplateSelector.
Here is the TemplateSelector class:
using System.Windows;
using System.Windows.Controls;
namespace Common.TemplateSelector
{
public class LanguageTemplateSelector : DataTemplateSelector
{
public DataTemplate TemplateEnglish { get; set; }
public DataTemplate TemplateGerman { get; set; }
public const string LanguageIdentifier = "de";
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
return Configuration.Configuration.Language == LanguageIdentifier ? this.TemplateGerman : this.TemplateEnglish;
}
}
}
And here the template definition and the definition of the TemplateSelector defined in the <UserControl.Resources></UserControl.Resources> area:
<DataTemplate DataType="{x:Type model:Tbl_PackagingMaster_ID_PackagingType}" x:Key="PackagingTypeEnglish">
<Grid VerticalAlignment="Center" HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Source="{Binding TypeIcon, Converter={StaticResource StringToUriConverter}}" VerticalAlignment="Top" Grid.Column="0" Height="14" Margin="2" />
<TextBlock Text="{Binding PackagingTypeDescription}" Style="{StaticResource TextBlockMediumSmallBlackStyle}" Grid.Column="1"/>
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type model:Tbl_PackagingMaster_ID_PackagingType}" x:Key="PackagingTypeGerman">
<Grid VerticalAlignment="Center" HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Source="{Binding TypeIcon, Converter={StaticResource StringToUriConverter}}" VerticalAlignment="Top" Grid.Column="0" Height="14" Margin="2" />
<TextBlock Text="{Binding PackagingTypeDescriptionGerman}" Style="{StaticResource TextBlockMediumSmallBlackStyle}" Grid.Column="1"/>
</Grid>
</DataTemplate>
<templateSelector:LanguageTemplateSelector x:Key="PackagingTypeLanguageSelector"
TemplateEnglish="{StaticResource PackagingTypeEnglish}"
TemplateGerman="{StaticResource PackagingTypeGerman}" />
This is how I use it for the ComboBox:
<telerik:RadComboBox ItemsSource="{Binding PackagingTypesFilter}"
SelectedValue="{Binding SelectedPackagingTypeFilter}"
SelectedValuePath="ID_PackagingType"
ItemTemplateSelector="{StaticResource PackagingTypeLanguageSelector}" />
However, I'm still looking for a more elegant way to solve this.
I want to use CommandParameter attribute in a context menu associated to a DataTemplate. The commandParameter should contain a reference to the object that triggered the data template as shown in the code sample below. I tried to use "{Binding Path=this}" but it does not work because "this" is not a property. The command fires but I can't get the right parameter. Do any one have an idea on how to do this?
Note: I removed Command="{Binding DeleteSelectedMeetingCommand}" by replacing it with a reference to the view locator and the command was triggering.
<DataTemplate DataType="{x:Type Models:MeetingDbEntry}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Path=HostTeam}"/>
<TextBlock Grid.Column="1" Text="{Binding Path=GuestTeam}"/>
<TextBlock Grid.Column="2" Text="{Binding Path=Result}"/>
<Grid.ContextMenu>
<ContextMenu Name="MeetingMenu">
<MenuItem Header="Delete"
Command="{Binding
Source={StaticResource Locator},
Path=Main.DeleteSelectedMeetingCommand}"
CommandParameter="{Binding Path=this}"/>
</ContextMenu>
</Grid.ContextMenu>
</Grid>
</DataTemplate>
Thanks,
It is working with the code below. You just need to type {Binding} in the CommandParameter attribute in order to reference the property that triggered the DataTemplate.
<DataTemplate DataType="{x:Type Models:MeetingDbEntry}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Path=HostTeam}"/>
<TextBlock Grid.Column="1" Text="{Binding Path=GuestTeam}"/>
<TextBlock Grid.Column="2" Text="{Binding Path=Result}"/>
<Grid.ContextMenu>
<ContextMenu Name="MeetingMenu">
<MenuItem Header="Delete"
Command="{Binding
Source={StaticResource Locator},
Path=Main.DeleteSelectedMeetingCommand}"
CommandParameter="{Binding}"
/>
</ContextMenu>
</Grid.ContextMenu>
</Grid>
</DataTemplate>
I'd expose the DeleteSelectedMeetingCommand on the object it deletes and bind the context menu entry to it. Then add a member variable holding the object to delete to the command and initialize it with this in the object to delete that's holding the command.
Example:
public class DeletableObject
{
public ICommand DeleteCommand { get; }
public DeleteableObject()
{
DeleteCommand = new DeleteCommand(this);
}
}
public class DeleteCommand : ICommand
{
private DeletableObject _DeletableObject;
public DeleteCommand(DeletableObject deletableObject)
{
_DeletableObject = deletableObject;
}
// skipped the implementation of ICommand but it deletes _DeletableObject
}
Hope that helps.