So I’ve been slowly but surely porting the Drunktender system. I’ve done a bit on dynamically loading XAML and creating the button style I wanted but now I need to start hooking up some plumbing. I’d first like to give a very massive thank you to Jeremiah Morrill for helping me out when I ran into an issue.
First thing was I tracked down a flippin sweet grid system with animations. I grabbed the one from Kevin Moore and his WPF Bag-O-Tricks tool kit. By using the same dynamic loading XAML layout, I’ve updated it with with the new grid.
<Window x:Class="Drunktender.Wpf.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:atp="clr-namespace:Microsoft.Samples.KMoore.WPFSamples.AnimatingTilePanel;
assembly=J832.Wpf.BagOTricksLib"
xmlns:Wpf="clr-namespace:Drunktender.Wpf"
Title="Window1" Height="696" Width="496">
<Window.Resources>
<Style x:Key="SelectedImagesPanel" TargetType="ItemsControl">
<Setter Property="atp:AnimatingTilePanel.ItemHeight" Value="98" />
<Setter Property="atp:AnimatingTilePanel.ItemWidth" Value="120" />
<Setter Property="ItemsControl.ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<atp:AnimatingTilePanel AnimatesNewItem="true"
Attraction="2.0" Dampening="0.20" Variation="1.00" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel>
<TextBox
Text="{Binding RelativeSource={RelativeSource
AncestorType={x:Type Wpf:Window1}},
Path=AlteredText, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
<ItemsControl Focusable="false"
ItemsSource="{Binding RelativeSource=
{RelativeSource AncestorType={x:Type Wpf:Window1}},
Path=SelectedImages}"
Style="{StaticResource SelectedImagesPanel}" />
</StackPanel>
</Window>
To do the binding, I just need a bit of code in the window’s code behind file.
public SortableObservableCollection<Button> SelectedImages
{
get { return (SortableObservableCollection<Button>)GetValue(SelectedImagesProperty); }
set { SetValue(SelectedImagesProperty, value); }
}
public static readonly DependencyProperty SelectedImagesProperty =
DependencyProperty.Register("SelectedImages", typeof(SortableObservableCollection<Button>),
typeof(Window1),
new UIPropertyMetadata(new SortableObservableCollection<Button>()));
Now lets make this a bit cooler with the grid dynamically updating. We’ll use some LINQ and lambda expressions. In addition, to just listing the items, we’ll want these items sorted as well. I can do this with a SortableObservableCollection which I found on a MSDN forum which inherits from ObservableCollection. This will allow the collection to always be sorted rather than be a random mess over time.
public string AlteredText
{
get { return (string)GetValue(AlteredTextProperty); }
set { SetValue(AlteredTextProperty, value); }
}
public static readonly DependencyProperty AlteredTextProperty =
DependencyProperty.Register("AlteredText", typeof(string),
typeof(Window1),
new UIPropertyMetadata("", AlteredTextChanged));
private static void AlteredTextChanged(DependencyObject sender,
DependencyPropertyChangedEventArgs e)
{
var typedSender = sender as Window1;
if (typedSender == null)
return;
SetGrid(typedSender, e.NewValue as string);
}
private static void SetGrid(Window1 window, string newValue)
{
var images = window.SelectedImages;
var newDrinkDataset = Drinks.GetByDrinksPartialName(newValue);
// removing old
var drinks = from s in images
select ((Drink)s.DataContext);
var newDrinkIds = from d in newDrinkDataset
select d.DrinkId;
var currentDrinkIds = from d in drinks
select d.DrinkId;
var removeDrinkIds = currentDrinkIds.Except(newDrinkIds);
var addDrinkIds = newDrinkIds.Except(currentDrinkIds);
var buttonsToRemove = (from s in images
where removeDrinkIds.Contains(((Drink)s.DataContext).DrinkId)
select (s)).ToList();
var addDrinks = from d in newDrinkDataset
where addDrinkIds.Contains(d.DrinkId)
select d;
buttonsToRemove.ForEach(b => images.Remove(b));
// adding in good
addDrinks.ToList().ForEach(d => images.Add(new Button { Content = d.Name, DataContext = d }));
images.Sort(button => button.Content);
}
You’ll see with the TextBox, I have a few magical words like RelativeSource and UpdateSourceTrigger. RelativeSource will let me not have to set a DataContext and UpdateSourceTrigger is telling the TextBox in this context to update soon as the value changes. By default, the TextBox will only update when it loses focus and I want it to update every time.
We’ll need one last little bit so on load the grid will be pre-populated. In the constructor for the window, we need to just add in one additional line to accomplish this.
public Window1()
{
InitializeComponent();
SetGrid(this, string.Empty);
}
Here it is the extremely basic grid effect with a few snap shots.

Not much now but it is starting to build out nicely.