ListBox Data Binding With In-place Editing
How to get this code going:
- Create a Windows Presentation Foundation project named ListBoxSample4
- Add a new class file named Computer.cs
- Add a new class file named ComputerTemplateSelector.cs
- Paste the following code into the corresponding files.
Replace the contents of Window1.xaml with this:
<Window x:Class="ListBoxSample4.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="307" Width="291">
<Window.Resources>
<DataTemplate x:Key="compEditingTemplate" x:Name="compEditingTemplate">
<StackPanel>
<TextBox Text="{Binding Path=Name}" Name="computerName" LostFocus="computerName_LostFocus" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="compTemplate" x:Name="compTemplate">
<StackPanel>
<TextBlock FontSize="14" Text="{Binding Path=Name}" />
<TextBlock FontSize="10" Text="{Binding Path=Location}" />
<TextBlock FontSize="10" Text="{Binding Path=Make}" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="compBrokenTemplate" x:Name="compBrokenTemplate">
<StackPanel>
<TextBlock FontSize="14" Foreground="Red" Text="{Binding Path=Name}" />
<TextBlock FontSize="10" Foreground="Red" Text="Broken" />
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid Name="mainGrid" Background="AntiqueWhite">
<ListBox Name="computerList" Margin="0,35,0,52" />
<Button Height="23" Name="button1" VerticalAlignment="Bottom" Click="button1_Click">Pick me!</Button>
<Button Height="23" Width="120" Name="button2" VerticalAlignment="Bottom" HorizontalAlignment="Left"
Margin="10,0,0,25" Click="button2_Click">Break</Button>
<Button Height="23" Width="120" Name="button3" VerticalAlignment="Bottom" HorizontalAlignment="Right"
Margin="0,0,10,25" Click="button3_Click">Fix</Button>
<TextBlock Height="24" Name="textBlock1" VerticalAlignment="Top" Margin="0,9,0,0">
Select a ListBox item and press F2 to edit the name.
</TextBlock>
</Grid>
</Window>
Replace the contents of Window1.xaml.cs with this:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
namespace ListBoxSample4
{
public partial class Window1 : Window
{
public Boolean editStarted = false;
public Window1()
{
InitializeComponent();
ComputerTemplateSelector templateSelector = new ComputerTemplateSelector();
templateSelector.CompTemplate = Resources["compTemplate"] as DataTemplate;
templateSelector.CompBrokenTemplate = Resources["compBrokenTemplate"] as DataTemplate;
templateSelector.CompEditingTemplate = Resources["compEditingTemplate"] as DataTemplate;
computerList.IsSynchronizedWithCurrentItem = true;
computerList.ItemTemplateSelector = templateSelector;
computerList.ItemsSource = Computer.SampleComputers();
computerList.KeyUp += new KeyEventHandler(computerList_KeyUp);
computerList.ItemContainerGenerator.StatusChanged += new EventHandler(ItemContainerGenerator_StatusChanged);
}
void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
{
if (computerList.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated &&
ComputerTemplateSelector.EditedComputerId != null &&
!editStarted)
{
TextBox comp = FindChild(computerList, "computerName") as TextBox;
comp.SelectAll();
comp.Focus();
editStarted = true;
}
}
void computerList_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.F2)
{
// enter edit mode for the current item
Computer selectedComputer = computerList.SelectedItem as Computer;
if (selectedComputer != null)
{
ComputerTemplateSelector.EditedComputerId = selectedComputer.ComputerId;
computerList.Items.Refresh();
}
}
}
private void button1_Click(object sender, RoutedEventArgs e)
{
Computer selectedComputer = computerList.SelectedItem as Computer;
if (selectedComputer == null)
{
MessageBox.Show("Select something");
return;
}
MessageBox.Show("You have selected " + selectedComputer.Name);
}
private void button2_Click(object sender, RoutedEventArgs e)
{
Computer selectedComputer = computerList.SelectedItem as Computer;
if (selectedComputer == null)
{
MessageBox.Show("Select something");
return;
}
selectedComputer.IsBoken = true;
// update UI
computerList.Items.Refresh();
}
private void button3_Click(object sender, RoutedEventArgs e)
{
Computer selectedComputer = computerList.SelectedItem as Computer;
if (selectedComputer == null)
{
MessageBox.Show("Select something");
return;
}
selectedComputer.IsBoken = false;
// update UI
computerList.Items.Refresh();
}
private void computerName_LostFocus(object sender, RoutedEventArgs e)
{
// end editing
ComputerTemplateSelector.EditedComputerId = null;
computerList.Items.Refresh();
editStarted = false;
}
private static DependencyObject FindChild(DependencyObject dependencyObject, String childName)
{
if (dependencyObject == null)
{
return null;
}
if (dependencyObject is FrameworkElement &&
(dependencyObject as FrameworkElement).Name == childName)
{
return dependencyObject;
}
DependencyObject result = null;
for (int index = 0; index < VisualTreeHelper.GetChildrenCount(dependencyObject); index++)
{
result = FindChild(VisualTreeHelper.GetChild(dependencyObject, index), childName);
if (result != null)
{
break;
}
}
return result;
}
}
}
Replace the contents of Computer.cs with this:
using System;
using System.Collections.Generic;
namespace ListBoxSample4
{
public class Computer
{
private static List<Computer> sampleComputers = null;
public String Name { get; set; }
public String Location { get; set; }
public String Make { get; set; }
public Boolean IsBoken { get; set; }
private String computerId;
public string ComputerId
{
get { return computerId; }
}
public Computer(String name, String location, String make)
: this(name, location, make, false)
{
}
public Computer(String name, String location, String make, Boolean isBroken)
{
Name = name;
Location = location;
Make = make;
IsBoken = isBroken;
computerId = Guid.NewGuid().ToString();
}
public static IEnumerable<Computer> SampleComputers()
{
if (sampleComputers == null)
{
sampleComputers = new List<Computer>();
sampleComputers.Add(new Computer("Kitchen PC", "On the kitchen counter", "DELL AX443"));
sampleComputers.Add(new Computer("NAS", "Network attached storage", "NSLU2"));
sampleComputers.Add(new Computer("Media1", "Media server", "DELL VISTA"));
sampleComputers.Add(new Computer("XBOX360", "Playing more", "MS", true));
sampleComputers.Add(new Computer("KidPC", "Kids play stuff", "HP1"));
}
return sampleComputers;
}
}
}
Replace the contents of ComputerTemplateSelector.cs with this:
using System;
using System.Windows;
using System.Windows.Controls;
namespace ListBoxSample4
{
public class ComputerTemplateSelector : DataTemplateSelector
{
public static string EditedComputerId = null;
private DataTemplate compTemplate;
private DataTemplate compBrokenTemplate;
private DataTemplate compEditingTemplate;
public DataTemplate CompTemplate
{
get { return compTemplate; }
set { compTemplate = value; }
}
public DataTemplate CompBrokenTemplate
{
get { return compBrokenTemplate; }
set { compBrokenTemplate = value; }
}
public DataTemplate CompEditingTemplate
{
get { return compEditingTemplate; }
set { compEditingTemplate = value; }
}
public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)
{
Computer computer = item as Computer;
if (computer == null)
{
throw new ArgumentException("Item must be a Computer");
}
if (computer.ComputerId == EditedComputerId)
{
return compEditingTemplate;
}
else
{
if (!computer.IsBoken)
{
return compTemplate;
}
else
{
return compBrokenTemplate;
}
}
}
}
}
Compile and run.
|