Binding some combobox to one collection - c#

I have my userControl element on a window and now I must connect comboboxes inside these userControls to ObcervableCollections on the ViewModel. But I can't. I linked the collections to the items, but get the following error - when I change the selection in one combo box, I automatically get the changes for the others. How to unbind the SelectedItem of a combo box to use 1 collection for multiple items with an independent selection. My control has this interface (for example).
<uielements:DeviceParametersControl Grid.Column="1"
Margin="2,2"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
EndColor="#3B191919"
NumberOfSystem="2"
MaxFaultPressureValue="{Binding DataContext.SelectedParameter[1].MaxFaultPressureValue, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Control}}}"
MaxWorkPressureValue="{Binding DataContext.SelectedParameter[1].MaxWorkPressureValue, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Control}}}"
MinWorkPressureValue="{Binding DataContext.SelectedParameter[1].MinWorkPressureValue, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Control}}}"
TestTimeValue="{Binding DataContext.SelectedParameter[1].TestTimeValue, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Control}}}"
PulseTimeValue="{Binding DataContext.SelectedParameter[1].PulseTimeValue, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Control}}}"
PauseTimeValue="{Binding DataContext.SelectedParameter[1].PauseTimeValue, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Control}}}"
PulsesCount="{Binding DataContext.SelectedParameter[1].PulsesCount, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Control}}}"
PulsesAcceleration="{Binding DataContext.SelectedParameter[1].PulsesAcceleration, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Control}}}"
Mode="{Binding DataContext.SelectedParameter[1].Mode,UpdateSourceTrigger=PropertyChanged, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Control}}}"
StartColor="#3BFFFFFF"
TestName="{Binding DataContext.SelectedParameter[1].Name, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Control}}}"
UpdateDataToDbCommand="{Binding DataContext.UpdateDataToDbCommand,RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Control}}}"
UpdateDataToPlcCommand="{Binding DataContext.UpdateDataToPlcCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Control}}}"
ItemsSource="{Binding DataContext.Parameters, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
DisplayMemberPath="Value"
SelectedValuePath="Id"
SelectedValue="{Binding DataContext.SelectedItem4Two, Mode=OneWayToSource, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}">
</uielements:DeviceParametersControl>

Use a different Object to each Components and selection like this :
XAML Code :
<Window x:Class="TestMVVMLight.MainWindow"
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:local="clr-namespace:TestMVVMLight"
mc:Ignorable="d"
DataContext="{Binding Main, Source={StaticResource Locator}}"
Title="MainWindow" Height="450" Width="800">
<Grid>
<ComboBox HorizontalAlignment="Left" Margin="27,113,0,0" SelectedValue="{Binding SelectedParameter1}" VerticalAlignment="Top" Width="120" ItemsSource="{Binding Parameters}" DisplayMemberPath="Value"/>
<ComboBox HorizontalAlignment="Left" Margin="171,113,0,0" SelectedValue="{Binding SelectedParameter2}" VerticalAlignment="Top" Width="120" ItemsSource="{Binding Parameters}" DisplayMemberPath="Value"/>
</Grid>
</Window>
ViewModel Code :
public class MainViewModel : ViewModelBase
{
public MainViewModel()
{
ObservableCollection<Parameter> parameters = new ObservableCollection<Parameter>();
for (int i = 0; i < 6; i++)
{
parameters.Add(new Parameter { Value = "Value " + i });
}
Parameters = parameters;
}
public ObservableCollection<Parameter> Parameters { get; set; }
public Parameter SelectedParameter1 { get; set; }
public Parameter SelectedParameter2 { get; set; }
}

// XAML
// first control
ItemsSource="{Binding DataContext.Parameters, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
SelectedValue="{Binding DataContext.SelectedItem4One, Mode=OneWayToSource, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}">
// second control
ItemsSource="{Binding DataContext.Parameters, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
SelectedValue="{Binding DataContext.SelectedItem4Two, Mode=OneWayToSource, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}">
// ViewModel
// all strings from database
public ICollectionView Parameters => this._model.Parameters.View;
// array for selected elements - it has 5 elements for each control
public ObservableCollection<Parameters> SelectedParameter => this._model.SelectedParameter;
public object SelectedItem4One
{
set
{
if (value == null || value == _selectedItem4One) return;
_selectedItem4One = value;
this._model.GetParametersById(0, (int)_selectedItem4One);
}
}
// - function from Model
public async Task GetParametersById(int index, int id)
{
try
{
var response = await _dataAccessService.DatabaseInterface
.GetByIdAsync(id)
.WithTimeout(TimeSpan.FromSeconds(TimeOutConnection));
this.SelectedParameter[index] = response.FirstOrDefault() ?? new Parameters();
OnPropertyChanged(new PropertyChangedEventArgs(nameof(SelectedParameter)));
}
catch (Exception e)
{
Message =
"Ошибка получения набора параметров для выбранного рецепта из базы данных по Id.\n" + e.Message +
e.InnerException;
OnMessageChanged(new PropertyChangedEventArgs(nameof(Message)));
}
}

Related

Binding Tag property of checkbox to ancestor datacontext

I know this is a frequently question but after viewing lots of question in this context i still did not find working solution.
I have this MainWindow
public partial class MainWindow : Window
{
public ObservableCollection<Camera> Cameras { get; set; } = new ObservableCollection<Camera>();
public ObservableCollection<Group> Groups { get; set; } = new ObservableCollection<Group>();
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
}
And this class
public class Group : INotifyPropertyChanged
{
private int _number;
[XmlAttribute("Number")]
public int Number
{
get { return _number; }
set
{
_number = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
This is part of the MainWindow.xaml (the relevant part)
<StackPanel>
<Button Click="Button_Click_1" Margin="55,0,0,0" Padding="4">Add Group</Button>
<ListView Grid.ColumnSpan="3" Grid.Row="1" ItemsSource="{Binding Groups,Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Margin="3" Width="30" Grid.Column="0" Text="{Binding Number}"></TextBlock>
<ComboBox Margin="3" Width="50" Grid.Column="5" ItemsSource="{Binding DataContext.Cameras, RelativeSource={RelativeSource AncestorType=ListView}}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Width="20" VerticalAlignment="Center" Tag="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}, Path=DataContext.Number}" Checked="OnCbObjectCheckBoxChecked" Unchecked="OnCbObjectCheckBoxChecked" />
<!--<CheckBox Width="20" VerticalAlignment="Center" Tag="{Binding Path=DataContext.Number, RelativeSource={RelativeSource AncestorType=ListView}}" Checked="OnCbObjectCheckBoxChecked" Unchecked="OnCbObjectCheckBoxChecked" />-->
<TextBlock Text="{Binding Path=Name, Mode=TwoWay}"></TextBlock>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
The list of checkbox inside the comboxbox will be filled according to the list of the cameras.
I want to bind the property "Tag" of the inner checkbox to the member Groups.Number like i did with the textblock above it.
The reason behind this (maybe you have another solution) is that the list of groups is a dynamic group, and i want to identify from which group the checkbox was checked.
I've tried everything with the ancestor issue but nothing seems to work.
other things i've tried are:
<CheckBox Width="20" VerticalAlignment="Center" Tag="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}, Path=DataContext.Number}" Checked="OnCbObjectCheckBoxChecked" Unchecked="OnCbObjectCheckBoxChecked" />
<CheckBox Width="20" VerticalAlignment="Center" Tag="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}, Path=DataContext.Groups.Number}" Checked="OnCbObjectCheckBoxChecked" Unchecked="OnCbObjectCheckBoxChecked" />
<CheckBox Width="20" VerticalAlignment="Center" Tag="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}, Path=Number}" Checked="OnCbObjectCheckBoxChecked" Unchecked="OnCbObjectCheckBoxChecked" />
<CheckBox Width="20" VerticalAlignment="Center" Tag="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}, Path=Groups.Number}" Checked="OnCbObjectCheckBoxChecked" Unchecked="OnCbObjectCheckBoxChecked" />
What do i miss here?
Ty!
ListView has the wron DataContext. It is outside the DataTemplate and is set to MainWindow. The DataTemplate that targets Group has the proper DataContext, of course the current Group item. You must chose an element of this DataTemplate as binding source. You couls bind to the ComboBox.DataContext:
<CheckBox Tag="{Binding RelativeSource={RelativeSource AncestorType=ComboBox}, Path=DataContext.Number}" />

WPF Input KeyBinding for a ListBox Item

I'm having a WPF Application, programatically I'm setting the focus to the ListBox Item, after that using UP / Down arrow I'm navigating from one Item to another Item. I need to Implement ENTER KeyEvent for that appropriate Item, it should trigger the ICommand SelectItemCommand in the ViewModel.
Consider the ViewModel Code:
public class MobileViewModel
{
public ObservableCollection<Mobile> MobileCollection { get; set; }
public MobileViewModel()
{
MobileCollection = new ObservableCollection<Mobile>()
{
new Mobile() { ID = 1, Name = "iPhone 6S", IsSelected = false },
new Mobile() { ID = 2, Name = "Galaxy S7", IsSelected = false }
}
}
public ICommand SelectItemCommand
{
get
{
return new DelegatingCommand((obj) =>
{
// Enter Key Event Operation
});
}
}
}
public class Mobile
{
public int ID { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}
The XAML Code is
<ListBox ItemsSource="{Binding MobileCollection}" x:Name="KeyListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<Button Command="{Binding SelectItemCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MobileViewModel}}}" CommandParameter="{Binding }">
<Button.InputBindings>
<KeyBinding Key="Enter" Command="{Binding SelectItemCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MobileViewModel}}}" CommandParameter="{Binding }" />
</Button.InputBindings>
<Button.Content>
<StackPanel>
<TextBlock Text="{Binding Name}" />
</StackPanel>
</Button.Content>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
My requirement is to trigger the ICommand while on Keyboard ENTER Key hit. I tried the KeyBinding inside the Button, but its not happening. Kindly assist me.
The ListBox Key Binding is
<ListBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding DataContext.SelectItemCommand, ElementName=KeyListBox}"
CommandParameter="{Binding SelectedItem,
RelativeSource={RelativeSource FindAncestor, AncestorType=ListBox}}"/>
</ListBox.InputBindings>
You should specify the Element Name and bind using DataContext. Then It should be work
The Complete XAML Source Code is
<ListBox Name="KeyListBox" ItemsSource="{Binding MobileCollection}" HorizontalAlignment="Left" Height="Auto" VerticalAlignment="Top" Width="300" HorizontalContentAlignment="Stretch">
<ListBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding DataContext.SelectItemCommand, ElementName=lstBox}" CommandParameter="{Binding SelectedItem, RelativeSource={RelativeSource FindAncestor, AncestorType=ListBox}}"/>
</ListBox.InputBindings>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Button Command="{Binding DataContext.SelectItemCommand, ElementName=lstBox}" CommandParameter="{Binding }" Foreground="Black" Padding="12 10" HorizontalContentAlignment="Left">
<Button.Content>
<StackPanel>
<CheckBox IsChecked="{Binding IsSelected, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Foreground="#404040">
<CheckBox.Content>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name, IsAsync=True}" TextWrapping="Wrap" MaxWidth="270" />
</StackPanel>
</CheckBox.Content>
</CheckBox>
</StackPanel>
</Button.Content>
</Button>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
You could put the InputBinding on the ListBox itself, passing through the selected item as the command parameter.
<ListBox ItemsSource="{Binding MobileCollection}" x:Name="KeyListBox">
<ListBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding SelectItemCommand}" CommandParameter="{Binding SelectedItem, RelativeSource={RelativeSource FindAncestor, AncestorType=ListBox}}"/>
</ListBox.InputBindings>
</ListBox>

bind command to nested listbox

I'm trying to bind a Command to a nested ListBox inside an itemsControl but somehow I can't find the right DataContext to execute the command.
XAML
<UserControl DataContext="{Binding VM1, Source={StaticResource Locator}}"
<ItemsControl ItemsSource="{Binding SceneList}"
<ListBox ItemsSource="{Binding PartialScenes}"
SelectedItem="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}, Path=DataContext.SelectedPartialScene}" >
<ListBox.InputBindings>
<KeyBinding Key="Delete" Command="{Binding DeleteSelectedPartialCommand}"/>
</ListBox.InputBindings>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock>
<Run Text="{Binding Path=Label}"/>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</ItemsControl
</UserControl
VM
public class VM1
{
public()
{
DeleteSelectedPartialCommand= new RelayCommand(Delete);
}
public RelayCommand DeleteSelectedPartialCommand{ get; private set; }
private void Delete()
{
Collection.Remove(SelectedItem);
}
}
I've tried
Command="{Binding Path=DataContext.DeleteSelectedPartialCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}}" />
and
Command="{Binding Path=DataContext.DeleteSelectedPartialCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}}" />
Both options are not working.
You need to access the root DataContext which is in UserControl.
Add a name to your UserControl
x:Name="MyUserControl"
And then for your command:
Command"{Binding ElementName=MyUserControl, Path=DataContext.DeleteSelectedPartialCommand}"

Binding to two different levels when ContextMenu inside an ItemsControl

I need to bind Command and CommandParameter to two different classes from within a WPF ContextMenu MenuItem that is inside an ItemsControl.ItemTemplate. The problem is that ContextMenu has a separate visual tree than the rest of the window. I got it working in .NET 4.0+ but can't find a workaround that works in .NET 3.5.
Note: Even the working .NET 4.0+ workaround works at runtime but breaks both the Visual Studio 2013 Designer and the Blend Designer.
How can I bind the CommandParameter to a single CustomerViewModel and bind the Command to EditCustomersController in .NET 3.5?
View
<Window
x:Class="MvvmLight1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MVVM Light Application"
DataContext="{Binding EditCustomers, Source={StaticResource Locator}}">
<ItemsControl
x:Name="rootElement"
ItemsSource="{Binding Customers}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock
Text="{Binding Name}">
<TextBlock.ContextMenu>
<ContextMenu
PlacementTarget="{Binding ElementName=myTextBlock}">
<MenuItem
Header="Capitalize Using RelativeSource (Does not work)"
CommandParameter="{Binding}"
Command="{Binding
Path=DataContext.CapitalizeCommand,
RelativeSource={RelativeSource
FindAncestor,
AncestorType={x:Type Window}}}" />
<MenuItem
Header="Lowercase Using RelativeSource (Does not work)"
CommandParameter="{Binding}"
Command="{Binding
Path=DataContext.LowercaseCommand,
RelativeSource={RelativeSource
FindAncestor,
AncestorType={x:Type Window}}}" />
<MenuItem
Header="Capitalize Using Source (Only works in .NET 4.0+)"
CommandParameter="{Binding}"
Command="{Binding
Path=DataContext.CapitalizeCommand,
Source={x:Reference Name=rootElement}}" />
<MenuItem
Header="Lowercase Using Source (Only works in .NET 4.0+)"
CommandParameter="{Binding}"
Command="{Binding
Path=DataContext.LowercaseCommand,
Source={x:Reference Name=rootElement}}" />
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Window>
Controller
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System.Collections.Generic;
using System.Windows.Input;
public class EditCustomersController : ViewModelBase
{
public EditCustomersController()
{
this.CapitalizeCommand = new RelayCommand<CustomerViewModel>(this.Capitalize);
this.LowercaseCommand = new RelayCommand<CustomerViewModel>(this.Lowercase);
var c = new List<CustomerViewModel>();
c.Add(new CustomerViewModel("Fred"));
c.Add(new CustomerViewModel("Bob"));
c.Add(new CustomerViewModel("Sue"));
c.Add(new CustomerViewModel("Sally"));
this.Customers = c;
}
public IEnumerable<CustomerViewModel> Customers { get; set; }
public ICommand CapitalizeCommand { get; private set; }
public ICommand LowercaseCommand { get; private set; }
private void Capitalize(CustomerViewModel customer)
{
customer.Name = customer.Name.ToUpper();
}
private void Lowercase(CustomerViewModel customer)
{
customer.Name = customer.Name.ToLower();
}
}
ViewModel
using GalaSoft.MvvmLight;
public class CustomerViewModel : ViewModelBase
{
private string name;
public CustomerViewModel(string name)
{
this.name = name;
}
public string Name
{
get
{
return this.name;
}
set
{
this.Set(() => this.Name, ref this.name, value);
}
}
}
Got it working in all versions of .NET by moving the ContextMenu into a resource and passing the top level DataContext through using the Tag property. Inside the ContextMenu MenuItem I can access both the current CustomerViewModel using {Binding} and the EditCustomersController using a binding with the Tag and RelativeSource.
View
<Window
x:Class="MvvmLight1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MVVM Light Application"
DataContext="{Binding EditCustomers, Source={StaticResource Locator}}">
<Window.Resources>
<ContextMenu
x:Key="ItemContextMenu"
Tag="{Binding PlacementTarget.Tag,
RelativeSource={RelativeSource Self}}">
<MenuItem
Header="Capitalize"
CommandParameter="{Binding}"
Command="{Binding Tag.CapitalizeCommand,
RelativeSource={RelativeSource
FindAncestor,
AncestorType={x:Type ContextMenu}}}" />
</ContextMenu>
</Window.Resources>
<ItemsControl
ItemsSource="{Binding Customers}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock
Tag="{Binding
DataContext,
RelativeSource={RelativeSource
AncestorType={x:Type Window}}}"
Text="{Binding Name}"
ContextMenu="{StaticResource ItemContextMenu}">
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Window>

How can I bind a command from my IntemsControl list to my main ViewModel?

How can I bind a command from my IntemsControl list to my main ViewModel?
<Window x:Class="MemoryGame.MainWindow"
...
DataContext="{Binding Main, Source={StaticResource Locator}}">
<Window.Resources>
<me:ColorConverter x:Key="ColorConverter"/>
</Window.Resources>
<Grid x:Name="LayoutRoot" Background="#FF44494D">
<ItemsControl ItemsSource="{Binding GameBoard.CardList}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle x:Name="Card01" Fill="{Binding Converter={StaticResource ColorConverter}}" Height="100" Width="100" Margin="10,10,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" Stroke="Black">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding SelectCardCommand, ???????????}" CommandParameter="{Binding Name, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Rectangle}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Rectangle>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
...
SelectCardCommand is defined in my main window ViewModel. I already tryed to add RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window} but it doesn't work.
---- EDIT More information ----
In my DataContext ViewModel I have this :
public class MainViewModel : ViewModelBase
{
private RelayCommand<string> _selectCardCommand;
public RelayCommand<string> SelectCardCommand
{
get
{
return _selectCardCommand;
}
}
public MainViewModel()
{
_selectCardCommand = new RelayCommand<string>((s) => DoSelectCardCommand(s));
// GameBoard = new Board();
// this.StartGame();
}
private void DoSelectCardCommand(string card)
{
// Code here
}
}
you can use two methods
using RelativeSource
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding DataContext.SelectCardCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ItemsControl}}"
CommandParameter="{Binding Name, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Rectangle}}"/>
</i:EventTrigger>
or using ElementName
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding DataContext.SelectCardCommand, ElementName=LayoutRoot}"
CommandParameter="{Binding Name, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Rectangle}}"/>
</i:EventTrigger>
EDIT
after executing the code I realized the reason, as rectangle do not have any event named Click so it does not bind, however you can bind to UIElement.MouseDown
alternatively I came up with a different approach to solve your issue.
I modify the template a bit to use Button and templated the button as needed and also changed the ItemsPanelTemplate so it look more like a memory game
<ItemsControl ItemsSource="{Binding GameBoard.CardList}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Command="{Binding DataContext.SelectCardCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ItemsControl}}"
CommandParameter="{Binding}">
<Button.Template>
<ControlTemplate>
<Rectangle Fill="{Binding Converter={StaticResource ColorConverter}}"
Height="100"
Width="100"
Margin="10,10,0,0"
Stroke="Black">
</Rectangle>
</ControlTemplate>
</Button.Template>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
the command
#region SelectCardCommand
public RelayCommand<Card> SelectCardCommand { get; private set; }
#endregion
public MainViewModel()
{
SelectCardCommand = new RelayCommand<Card>((s) => DoSelectCardCommand(s));
GameBoard = new Board();
this.StartGame();
}
private void DoSelectCardCommand(Card card)
{
if (card != null)
card.Upside = true;
}
this will help you remove int.Parse(card.Substring(4,2)); and other string manipulations too

Categories