I have created a simple UI with Command binding for the Button and Combo Box. My intention is to populate the list of Button based upon the combo box selected value on Lost Focus event as like below code.
public partial class MainWindow : Window
{
public MainWindow()
{
ViewModel ViewModel = new ViewModel();
this.DataContext = ViewModel;
//Test Data Feeded
ViewModel.SelectedServer = ViewModel.ServerList.First();
ViewModel.MyList = new ObservableCollection<Model>();
for (int i = 0; i < Convert.ToInt16(ViewModel.SelectedServer); i++)
{
ViewModel.MyList.Add(new Model() { Name = (i + 1).ToString() });
}
InitializeComponent();
txtServer.Focus();
}
}
public class ViewModel: BaseDataMdel
{
ObservableCollection<Model> _MyList;
List<string> serverList;
string selectedServer;
void Validated()
{
//Bsaed upon some validation we repopulate the collection
if (MyList == null) MyList = new ObservableCollection<Model>(); else MyList.Clear();
for (int i = 0; i < Convert.ToInt16(SelectedServer); i++)
{
MyList.Add(new Model() { Name = (i + 1).ToString() });
}
}
private void ActionRequestedEvent(object param)
{
switch(param.ToString())
{
case "DataSetServerLostFocus":
{
Validated();
}
break;
default:
MessageBox.Show(param.ToString()); break;
}
}
private ICommand _ActionCommand1;
public ICommand ActionCommand1
{
get
{
if (_ActionCommand1 == null)
this._ActionCommand1 = new RelayCommand(param =>
{
ActionRequestedEvent(param);
});
return _ActionCommand1;
}
set
{
_ActionCommand = value;
}
}
private ICommand _ActionCommand;
public ICommand ActionCommand
{
get
{
if (_ActionCommand == null)
this._ActionCommand = new RelayCommand(param =>
{
ActionRequestedEvent(param);
});
return _ActionCommand;
}
set
{
_ActionCommand = value;
}
}
public ObservableCollection<Model> MyList
{
get
{
return _MyList;
}
set
{
_MyList = value;
RaisePropertyChanged(nameof(MyList));
}
}
public List<string> ServerList
{
get
{
return serverList;
}
set
{
serverList = value;
RaisePropertyChanged(nameof(ServerList));
}
}
public string SelectedServer
{
get
{
return selectedServer;
}
set
{
selectedServer = value;
RaisePropertyChanged(nameof(SelectedServer));
}
}
public ViewModel()
{
ServerList = new List<string>() { "1", "2", "3", "4", "5" };
}
}
Xaml code
<Window x:Class="WpfApplication26.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:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:local="clr-namespace:WpfApplication26"
mc:Ignorable="d" Name="Group"
Title="MainWindow" Height="350" Width="525">
<StackPanel Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
<ComboBox Width="150" Name="txtServer" ItemsSource="{Binding ServerList}" SelectedItem="{Binding SelectedServer}" Height="25">
<i:Interaction.Triggers>
<i:EventTrigger EventName="LostFocus">
<i:InvokeCommandAction Command="{Binding ActionCommand}" CommandParameter="DataSetServerLostFocus"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
<GroupBox Header="Test Case" Width="175" Height="200">
<ItemsControl ItemsSource="{Binding MyList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="2">
<TextBox Width="120" Text="{Binding Name}"/>
<Button Content=".." Height="25" Width="25" Margin="3 0 0 0"
Command="{Binding DataContext.ActionCommand,ElementName=Group}"
CommandParameter="{Binding Name}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</GroupBox>
</StackPanel>
</Window>
- Run the code.
- Click the Button on the ListView.
- See that the command is not invoked on the first click.
I Know that is happening due to re-iteration of the collection.
steps Tried to overcome this:
Store the button in the temp variable before re-iteration and invoke the button click event programmatically after the update, this helps for me to resolve my issue partially. Because
Window.GetWindow(button)
returning null for the backup button.
Is there any way to over come this problem.