Ok, this is not a direct answer to your question, but rather a complete refactoring of your code the "right" way.
First thing you must understand when programming in WPF, is that UI is not Data and act accordingly.
That makes your following code:
ListBoxItem lbi1 = new ListBoxItem();
lbi1.Content = "Introduction"; lbi1.Name = "get" + lbi1.Content;
listMethods.Items.Add(lbi1);
//... etc boilerplate
completely irrelevant and undesired.
the ListBoxItems
are not your concern. Your code should not use nor reference them. That's up to the UI to create the proper ListBoxItems
given the proper data structures and Collections
are provided.
This is the most important realization you must have when coming from traditional UI programming into MVVM-able XAML based frameworks.
Therefore, the first thing you must ALWAYS do when creating new UIs in WPF is to Create a proper Data Structure:
public class ActionItem
{
public string DisplayName { get; set; }
public Action Action { get; set; }
}
This is the data that will be represented by the ListBoxItems
, with a DisplayName
to be shown in the UI, and an Action
delegate to execute.
As per the linked MSDN article, The System.Action
delegate
Encapsulates a method that has no parameters and does not return a value.
Therefore it's perfectly suitable for our current needs. We need a reference to a method (that's what a delegate actually is) that takes no parameters and does not return anything, something like:
public void SimpleMethod()
{
Result += "Simple Method!";
}
Also notice that C# supports the concept of Anonymous Methods and Lambda Expressions to actually write these kind of simple methods in shorter syntaxes.
For example, the above SimpleMethod()
could be reduced to a Lambda Expression like:
() => Result += "Simple Method!";
This removes the need to declare an additional identifier (the method name) and simplifies and helps keep code clean.
Going back to our example, the second thing you need when creating WPF UIs is the ViewModel
, this class actually represents (and holds) the data that will be shown on screen:
public class ActionsViewModel: PropertyChangedBase
{
public ObservableCollection<ActionItem> AvailableActions { get; set; }
public ObservableCollection<ActionItem> SelectedActions { get; set; }
public ActionItem FocusedAction1 { get; set; }
public ActionItem FocusedAction2 { get; set; }
private string _result;
public string Result
{
get { return _result; }
set
{
_result = value;
OnPropertyChanged("Result");
}
}
public ActionsViewModel()
{
AvailableActions = new ObservableCollection<ActionItem>
{
new ActionItem() {DisplayName = "Introduction", Action = () => Result += " Hello there!"},
new ActionItem() {DisplayName = "Greeting", Action = () => Result += " How are you today?"},
new ActionItem() {DisplayName = "Story", Action = () => Result += " I once met a goat and his name was billy, and he lived on a plain that was very hilly."},
new ActionItem() {DisplayName = "My Name", Action = () => Result += "My name is too infinity!"},
new ActionItem() {DisplayName = "Conclusion", Action = () => Result += "That is all, goodbye!"}
};
SelectedActions = new ObservableCollection<ActionItem>();
}
public void AddAction()
{
var focused = FocusedAction1;
if (focused != null)
{
AvailableActions.Remove(focused);
SelectedActions.Add(focused);
}
}
public void DeleteAction()
{
var focused = FocusedAction2;
if (focused != null)
{
SelectedActions.Remove(focused);
AvailableActions.Add(focused);
}
}
public void Run()
{
Result = string.Empty;
SelectedActions.ToList().ForEach(x => x.Action());
}
}
Notice that this class has no interaction (nor reference) to any UI element. In MVVM (the preferred and easier approach to WPF), the Application Logic and Data must be completely decoupled from the UI. This enables a high level of customizability to both parts without too much interdependence of one another.
Also notice that I'm defining 2 ObservableCollection<ActionItem>
, these are the ones that will be represented on-screen by the 2 ListBox
es, Whereas FocusedAction1
and FocusedAction2
represent the highlighted item in each ListBox
, and finally a string Result
property that will be used to store the results.
Also Notice that in order to support Two Way DataBinding, the ViewModel classes must implement the INotifyPropertyChanged interface, therefore our ViewModel is derived from a PropertyChangedBase
class that looks like this:
public class PropertyChangedBase:INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
Application.Current.Dispatcher.BeginInvoke((Action) (() =>
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}));
}
}
Next, we can proceed to actually define our UI:
<Window x:Class="MiscSamples.ActionsListBoxSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ActionsListBox" Height="600" Width="1000">
<DockPanel>
<StackPanel Orientation="Horizontal"
DockPanel.Dock="Top">
<Button Margin="2" Content="Add Action" Click="AddAction" />
<Button Margin="2" Content="Delete Action" Click="DeleteAction" />
<Button Margin="2" Content="Run" Click="Run"/>
</StackPanel>
<TextBox Text="{Binding Result}" DockPanel.Dock="Bottom" Height="28" IsReadOnly="True"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ListBox ItemsSource="{Binding AvailableActions}"
SelectedItem="{Binding FocusedAction1}"
DisplayMemberPath="DisplayName"/>
<ListBox ItemsSource="{Binding SelectedActions}"
SelectedItem="{Binding FocusedAction2}"
DisplayMemberPath="DisplayName"
Grid.Column="1"/>
</Grid>
</DockPanel>
</Window>
Notice that I've not named ANY elements in XAML. This helps a LOT when you need to get used to the MVVM mentality. The inability to actually manipulate any UI element from code behind makes you rethink your approach every time you feel the temptation of doing so.
Again, Im making extensive use of DataBinding
to connect the UI to the ViewModel
, that's why the need to manipulate the UI in code is eliminated.
You may have noticed another very important aspect of this approach: the reduction of boilerplate to almost zero. There's no casting stuff, no ToString()
no nothing of that, just simple, simple properties and DataBinding, That's how you develop in WPF.
Finally, the Code Behind, and some event handlers. I usually prefer to use Commands rather than Click handlers for Buttons, but for the simplicity of this sample, I'll stick to the traditional approach:
public partial class ActionsListBoxSample : Window
{
public ActionsViewModel ViewModel { get; set; }
public ActionsListBoxSample()
{
InitializeComponent();
DataContext = ViewModel = new ActionsViewModel();
}
private void AddAction(object sender, RoutedEventArgs e)
{
ViewModel.AddAction();
}
private void DeleteAction(object sender, RoutedEventArgs e)
{
ViewModel.DeleteAction();
}
private void Run(object sender, RoutedEventArgs e)
{
ViewModel.Run();
}
}
Notice how the Click handlers are merely reduced to executing logic in the ViewModel. That's a key concept, you must NEVER place application logic in the Code Behind.
All this gives the following result:

Notice that when clicking the Run
Button, all the Action
s in the right side are executed in order. Our job is done. No switch
, no casting, no ListBoxItem.
anything, no complicated visual tree manipulation stuff. Much more maintainable, scalable and beautiful code. That's what WPF and MVVM help to produce.
Edit: Adding a sample with Commands
, as per the OP's request:
Commands in WPF serve as abstractions of "user actions" (not only Button Clicks), for example, a KeyGesture
can be associated with a Command:
<TextBox>
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding SomeCommand}"/>
</TextBox.InputBindings>
</TextBox>
Also, many "clickable" UI elements (MenuItem
, Button
, CheckBox
, ToggleButton
) already have a Command
property that you can bind to some ICommand
implementation in the ViewModel.
This makes it very easy to wire up the UI elements to some behavior defined in the ViewModel. Again, the main goal here is to separate the UI elements and their events from the actual implementing code.
Here is the simplest Reusable ICommand
implementation I've been able to come up with:
//Dead-simple implementation of ICommand
//Serves as an abstraction of Actions performed by the user via interaction with the UI (for instance, Button Click)
public class Command : ICommand
{
public Action Action { get; set; }
public void Execute(object parameter)
{
if (Action != null)
Action();
}
public bool CanExecute(object parameter)
{
return IsEnabled;
}
private bool _isEnabled = true;
public bool IsEnabled
{
get { return _isEnabled; }
set
{
_isEnabled = value;
if (CanExecuteChanged != null)
CanExecuteChanged(this, EventArgs.Empty);
}
}
public event EventHandler CanExecuteChanged;
public Command(Action action)
{
Action = action;
}
}
So, we could now declare some properties of this Type in our existing ActionsViewModel
:
public Command AddActionCommand { get; set; }
public Command DeleteActionCommand { get; set; }
public Command RunCommand { get; set; }
and instantiate them in the constructor:
public ActionsViewModel()
{
//Existing code here
AddActionCommand = new Command(AddAction);
DeleteActionCommand = new Command(DeleteAction);
RunCommand = new Command(Run);
}
Notice that the Command
takes an Action
parameter in the constructor (again, a Reference to a Method), which will be executed when the command is invoked.
So, we now replace the Click handlers referenced in XAML for these commands:
<Button Margin="2" Content="Add Action" Command="{Binding AddActionCommand}" />
<Button Margin="2" Content="Delete Action" Command="{Binding DeleteActionCommand}" />
<Button Margin="2" Content="Run" Command="{Binding RunCommand}"/>
and then remove the Click handlers no longer needed from Code Behind, and since we also removed almost all code from there, we no longer need to even have a reference to the ViewModel anymore:
public partial class ActionsListBoxSample : Window
{
public ActionsListBoxSample()
{
InitializeComponent();
DataContext = new ActionsViewModel();
}
}
The result is exactly the same as before, but we have now moved even more stuff from the Code Behind into the ViewModel. This is just a simple example, but there are more complex types of Commands, such as Prism's DelegateCommand<T>
It's also important to mention that if the CanExecute()
method of the Command evaluates to false
after the CanExecuteChanged
event is raised, all relevant UI elements (I.E elements for which the Command
property is bound / set to the Command in question), these UI elements are actually automatically Disabled. This comes really handy when you think about it, as there might be many UI elements bound to the same command(s) in the ViewModel, and you don't have to manage these UI elements individually.