My name is Edward Tanguay. I'm an American software and web developer living and working in Berlin, Germany.
2 days ago: Posted new ObservableCollection MenuItem w/ TextBox, ItemContainerStyle, still doesn't work, but now in a different way: http://is.gd/1l58e.
2 days ago: Has anyone doing WPF successfully bound MenuItems to an ObservableCollection, looking for a working code example: http://is.gd/1l58e.
2 days ago: Video: what if JFK had been a CEO, speaker is my former roommate from college, lucid and entertaining as back in the day: http://is.gd/1l4fl.
3 days ago: Informative podcast on sharepoint with Sahil Malik, requires AD?, must run in VM?, no debugging? sounds cumbersome: http://is.gd/1jFz1.
4 days ago: Got SQLite installed and running on Debian VPS, here's how: http://is.gd/1iL68.
4 days ago: Purchased and set up a VPS within an hour on a Sunday afternoon, nice experience so far: http://www.server4you.de.
4 days ago: Podcast by Kevin Kelly on the future of the web, "cloud applications, all about data, wholly different than today's web": http://is.gd/1iKtr.
4 days ago: Enjoyable, 2-beer podcast, @shanselman, Franklin et al. get rolling, funny, pub-atmosphere geek talk, win7, surface, etc. http://is.gd/1iKbP.
5 days ago: Anyone know how I can post-install SQLite on a Suse VPS with automatic Apache/PHP setup? http://is.gd/1hm6X.
on Wednesday, June 24, 2009: C# CODE EXAMPLE: Three ways to create the same XML file (string concat, xmlwriter, linq-to-xml): http://is.gd/1ctco.

Custom Item Types

Developer Menu

Developer Admin Menu

C# CODE EXAMPLE created on Thursday, June 25, 2009 permalink
Four ways to create an XML file
Here are four ways to create the same XML string that I needed for an application: string concatenation, XmlWriter, LINQ-to-XML, in reverse order of preference (plus an example using XML literals which Jim Wooley posted on his site along with some notes on the dangers of string concatenation). These code samples assume an object called DataType which is not included in the code, so the code isn't executable as is, but I just wanted to record the syntax of each way for further reference. Notice the Enumerable.Range(1, 3).Select on the LINQ-to-XML functions as a for loop.
String Concatentation:
    StringBuilder sb = new StringBuilder();
    sb.Append("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + Environment.NewLine);

    sb.Append(String.Format("<{0}>{1}", _pluralCamelNotation, Environment.NewLine));
    for (int index = 0; index < 3; index++)
    {
        sb.Append(String.Format("\t<{0}>{1}", _singularCamelNotation, Environment.NewLine));
        foreach (DataType dataType in _allDataTypes)
        {
            sb.Append(String.Format("\t\t<{0}>{2}</{0}>{1}", dataType.CamelCaseNotation, Environment.NewLine, dataType.GetDummyData()));
        }
        sb.Append(String.Format("\t</{0}>{1}", _singularCamelNotation, Environment.NewLine));
    }
    sb.Append(String.Format("</{0}>{1}", _pluralCamelNotation, Environment.NewLine));

XmlWriter:
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.NewLineHandling = NewLineHandling.Entitize;
            settings.Indent = true;
            settings.IndentChars = "\t";

            StringBuilder sb = new StringBuilder();
            using (XmlWriter xw = XmlWriter.Create(sb, settings))
            {
                xw.WriteStartDocument();
                xw.WriteStartElement(_pluralCamelNotation);
                for (int i = 0; i < 3; i++)
                {
                    xw.WriteStartElement(_singularCamelNotation);
                    foreach (DataType dataType in _allDataTypes)
                    {
                        xw.WriteElementString(dataType.CamelCaseNotation, dataType.GetDummyData());
                    }
                    xw.WriteEndElement();
                }
                xw.WriteEndElement();
                xw.WriteEndDocument();
                xw.Close();
            }
            return sb.ToString();

XML Literals (VB.NET):

        Dim doc = <?xml version="1.0"?>
                    <<%= _pluralCamelNotation %>>
                        <%= From i In Enumerable.Range(1, 3) _
                            Select <<%= _singluarNotation %>>
                                     <%= From t In _allDataTypes _
                                         Select <<%= t.CamelCaseNotation %>>
                                             <%= t.GetDummyData %></> %>
                                 </> %>
                    </>

LINQ-to-XML:
            XDocument doc = new XDocument(
                new XDeclaration("1.0", null, null),
                new XElement(_pluralCamelNotation,
                    Enumerable.Range(1, 3).Select(
                        i => new XElement(_singularCamelNotation,
                            _allDataTypes.Select(
                                dataType => new XElement(
                                    dataType.CamelCaseNotation,
                                    dataType.GetDummyData())
                            )
                    ))));
            return doc.ToString();
post comment
 
WPF CODE EXAMPLE created on Wednesday, June 24, 2009 permalink
WPF/MVVM application with dynamic menu and buttons
This is a base WPF application with a View/ViewModel pattern and no code-behind, it loads the pages from an XML file. To create a new page you need to make a new entry in the XML, create a View and a ViewModel and it will automatically appear. The MainView is injected into each ViewModel so that each ViewModel can have buttons which go to other pages, there is an example of this on the Options page.
MainView.xaml:
<Window x:Class="TestMenu234.Views.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:c="clr-namespace:TestMenu234.Commands"
    xmlns:vm="clr-namespace:TestMenu234.ViewModels"
    xmlns:v="clr-namespace:TestMenu234.Views"
    xmlns:converters="clr-namespace:TestMenu234.Converters"
    Title="Main Window" Height="400" Width="630" MinWidth="630">

    <Window.Resources>
        <DataTemplate x:Key="CodeGenerationMenuTemplate">
            <MenuItem
                Header="{Binding Title}"
                Command="{Binding DataContext.SwitchPageCommand,
                RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Menu}}}"
                CommandParameter="{Binding IdCode}"/>
        </DataTemplate>
        
        <converters:PageItemViewAndViewModelMatcher x:Key="PageItemViewAndViewModelMatcher"/>
        <DataTemplate DataType="{x:Type vm:ViewModelPageItemBase}">
            <ContentControl Content="{Binding Converter={StaticResource PageItemViewAndViewModelMatcher}}"/>
        </DataTemplate>

    </Window.Resources>

    <DockPanel LastChildFill="True">

        <Menu DockPanel.Dock="Top">
            <MenuItem
                Header="Pages" ItemsSource="{Binding AllPageItemViewModels}"
                        ItemTemplate="{StaticResource CodeGenerationMenuTemplate}"/>
        </Menu>

        <Border DockPanel.Dock="Bottom" Padding="5 5 5 0" Background="#eee">
            <Grid Background="#eee">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" MinWidth="300"/>
                    <ColumnDefinition Width="200"/>
                    <ColumnDefinition Width="100"/>
                </Grid.ColumnDefinitions>
                <Slider
                Grid.Column="0"
                HorizontalAlignment="Left"
                Value="{Binding CurrentPageItemViewModelIndex}"
                Width="300"
                Minimum="0"
                Maximum="{Binding HighestPageItemIndex}"/>
                
                <TextBlock Grid.Column="1"
                             HorizontalAlignment="Center" FontWeight="Bold"
                             Text="{Binding CurrentPageItemViewModelTitle}"/>
                
                <DockPanel Grid.Column="2" Margin="0 0 0 5" LastChildFill="False">
                    <Button
                    Margin="3 0 0 0"
                    DockPanel.Dock="Right"
                HorizontalAlignment="Right"
                Content="Next" Command="{Binding NextPageCommand}"/>
                    <Button
                    DockPanel.Dock="Right"
                Content="Prev" Command="{Binding PreviousPageCommand}"/>
                </DockPanel>
            </Grid>
        </Border>

        <ContentControl
            DockPanel.Dock="Top"
            VerticalAlignment="Stretch"
            VerticalContentAlignment="Stretch"
            Content="{Binding CurrentPageItemViewModel}"/>

    </DockPanel>
</Window>

MainViewModel constructor:
        public MainViewModel()
        {

            PageItems pageItems = PageItems.Create("all");

            foreach (PageItem pageItem in pageItems.Collection)
            {
                string assemblyName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
                string viewModelName = assemblyName + ".ViewModels.PageItem" + StringHelpers.ForcePascalNotation(pageItem.IdCode) + "ViewModel";
                var type = Type.GetType(viewModelName);
                var viewModel = Activator.CreateInstance(type, this, pageItem) as ViewModelPageItemBase;
                AllPageItemViewModels.Add(viewModel);
            }

            CurrentPageItemViewModelIndex = 0;
            LoadCurrentPageItemViewModel();
        }
post comment
 
WPF CODE EXAMPLE created on Tuesday, June 23, 2009 permalink
How to create a WPF/MVVM application with dynamic menu
This application loads an XML file of "PageItems" which fill an ObservableCollection in the MainViewModel which builds a Menu dynamically. The user can also change the pages with a slider or by clicking the previous and next buttons. The title of the page is displayed at the bottom as well. For some reason when the user clicks on the icon area of the menu item, the DelegateCommand is not fired. I asked about the menu item issue on StackOverflow.
MainView.xaml:
<Window x:Class="TestMenu234.Views.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:c="clr-namespace:TestMenu234.Commands"
    xmlns:vm="clr-namespace:TestMenu234.ViewModels"
    xmlns:v="clr-namespace:TestMenu234.Views"
    Title="Main Window" Height="400" Width="630" MinWidth="630">

    <Window.Resources>
        <DataTemplate x:Key="CodeGenerationMenuTemplate">
            <MenuItem
                Header="{Binding Title}"
                Command="{Binding DataContext.SwitchPageCommand,
                RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Menu}}}"
                CommandParameter="{Binding IdCode}"/>
        </DataTemplate>
        
        
        <DataTemplate DataType="{x:Type vm:PageItemManageCustomersViewModel}">
            <v:PageItemManageCustomersView/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:PageItemManageEmployeesViewModel}">
            <v:PageItemManageEmployeesView/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:PageItemReportsViewModel}">
            <v:PageItemReportsView/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:PageItemOptionsViewModel}">
            <v:PageItemOptionsView/>
        </DataTemplate>


    </Window.Resources>

    <DockPanel LastChildFill="False">

        <Menu DockPanel.Dock="Top">
            <MenuItem
                Header="Pages" ItemsSource="{Binding AllPageViewModels}"
                        ItemTemplate="{StaticResource CodeGenerationMenuTemplate}"/>
        </Menu>

        <ContentControl
            DockPanel.Dock="Top"
            Content="{Binding CurrentPageItemViewModel}"/>

        <Border DockPanel.Dock="Bottom" Padding="5 5 5 0" Background="#eee">
            <Grid Background="#eee">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" MinWidth="300"/>
                    <ColumnDefinition Width="200"/>
                    <ColumnDefinition Width="100"/>
                </Grid.ColumnDefinitions>
                <Slider
                Grid.Column="0"
                HorizontalAlignment="Left"
                Value="{Binding CurrentPageItemViewModelIndex}"
                Width="300"
                Minimum="0"
                Maximum="{Binding HighestPageItemIndex}"/>
                
                <TextBlock Grid.Column="1"
                             HorizontalAlignment="Center" FontWeight="Bold" Text="{Binding CurrentPageItemViewModelTitle}"/>
                
                <DockPanel Grid.Column="2" Margin="0 0 0 5" LastChildFill="False">
                    <Button
                    Margin="3 0 0 0"
                    DockPanel.Dock="Right"
                HorizontalAlignment="Right"
                Content="Next" Command="{Binding NextPageCommand}"/>
                    <Button
                    DockPanel.Dock="Right"
                Content="Prev" Command="{Binding PreviousPageCommand}"/>
                </DockPanel>
            </Grid>
        </Border>

    </DockPanel>
</Window>
post comment
 
WPF CODE EXAMPLE created on Saturday, June 20, 2009 permalink
How to use MVVM pattern to validate an e-mail field as the user types
Most books would show you how to validate a field as the user is typing by creating a TextBox then adding a TextChanged event and handling that event in the code behind, or using a Validator class. However, if you are using the MVVM pattern, you can basically forget this since you don't want your code-behind side-stepping your ViewModel to get information from the database, etc. Instead, you need to bind the text of your TextBox to a property on your ViewModel like this Text="{Binding FieldEmail, UpdateSourceTrigger=PropertyChanged}"> and then attach a style to the TextBox which has DataTriggers that change the color based on another property on your ViewModel. This works well, is fully MVVM compliant, no code-behind.
XAML:
<Window x:Class="TestUpdateText.Views.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:c="clr-namespace:TestUpdateText.Commands"
    Title="Main Window" Height="400" Width="800">

    <Window.Resources>
        <Style x:Key="FieldEmailStyle" TargetType="TextBox">
            <Style.Triggers>
                <DataTrigger Binding="{Binding FieldEmailValidationStatus}" Value="invalid">
                    <Setter Property="TextBox.Background" Value="Yellow"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding FieldEmailValidationStatus}" Value="valid">
                    <Setter Property="TextBox.Background" Value="LightGreen"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>

    <DockPanel HorizontalAlignment="Left" LastChildFill="False" Margin="10">
        <StackPanel
            Orientation="Horizontal"
            HorizontalAlignment="Left"
            DockPanel.Dock="Top">

            <TextBlock
                FontSize="14"
                Text="E-Mail: "
                Margin="0 0 5 0"/>

            <TextBox
                Width="200"
                Style="{StaticResource FieldEmailStyle}"
                Text="{Binding FieldEmail, UpdateSourceTrigger=PropertyChanged}">
            </TextBox>

            <TextBlock
                FontSize="14"
                Text="{Binding FieldEmailMessage}"
                Margin="5 0 0 0"/>
        </StackPanel>

    </DockPanel>
</Window>

post comment
 
MVVM CODE EXAMPLE created on Friday, June 19, 2009 permalink
How to bind multiple XAML controls to one ObservableCollection in your ViewModel
This was an experiment to get control of how to bind various controls (ComboBox, ListBox, Slider) to one ObservableCollection (Customers) in the ViewModel. You can also add a new Customer by typing in a first and last name and only when both are filled out will the button be enabled. There is no code-behind in this example, all is being done with binding. When you move one control all others move as well.
XAML:
<Window x:Class="TestSelectedItem234.Views.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:c="clr-namespace:TestSelectedItem234.Commands"
    Title="Main Window" Height="600" Width="800">

    <Window.Resources>

        <DataTemplate x:Key="CustomerShowTemplate">
            <Border CornerRadius="5"
                    Background="#eee"
                    Padding="5"
                    HorizontalAlignment="Left">
                <StackPanel>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock FontSize="14" FontWeight="Bold" Text="{Binding FirstName}"/>
                        <TextBlock Text=" "/>
                        <TextBlock FontSize="14" FontWeight="Bold" Text="{Binding LastName}"/>
                    </StackPanel>
                    <TextBlock Text="{Binding Path=HireDate,
                        StringFormat='Hired on {0:MMM dd, yyyy}'}"/>
                </StackPanel>
            </Border>
        </DataTemplate>

        <DataTemplate x:Key="CustomerComboBoxTemplate">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding FirstName}"/>
                <TextBlock Text=" "/>
                <TextBlock Text="{Binding LastName}"/>
            </StackPanel>
        </DataTemplate>

        <DataTemplate x:Key="CustomerItemTemplate">
            <Border Background="#fff" Padding="2" >
                <Border CornerRadius="5" Width="400">
                    <Border.Background>
                        <LinearGradientBrush EndPoint="1.074,2.256" StartPoint="-0.182,-0.829">
                            <GradientStop Color="#FFCAA157" Offset="0"/>
                            <GradientStop Color="#FFE5C68D" Offset="1"/>
                        </LinearGradientBrush>
                    </Border.Background>
                    <StackPanel>
                        <TextBlock Margin="5" Foreground="#555">
                            <TextBlock.Text>
                                <MultiBinding StringFormat="{}{0} {1}">
                                    <Binding Path="FirstName"/>
                                    <Binding Path="LastName"/>
                                </MultiBinding>
                            </TextBlock.Text>
                        </TextBlock>
                    </StackPanel>
                </Border>
            </Border>
        </DataTemplate>

        <DataTemplate x:Key="CustomerItemTemplateSelected">
            <Border Background="#fff" Padding="2" >
                <Border CornerRadius="5" Width="400">
                    <Border.Background>
                        <LinearGradientBrush EndPoint="0.09,1.066" StartPoint="0.89,-0.531">
                            <GradientStop Color="#FFFBCE29" Offset="1"/>
                            <GradientStop Color="#FFE5A646" Offset="0"/>
                        </LinearGradientBrush>
                    </Border.Background>
                    <StackPanel>
                        <TextBlock FontSize="18" Margin="10 5 10 5" Foreground="#000">
                            <TextBlock.Text>
                                <MultiBinding StringFormat="{}{0} {1}">
                                    <Binding Path="FirstName"/>
                                    <Binding Path="LastName"/>
                                </MultiBinding>
                            </TextBlock.Text>
                        </TextBlock>
                        <TextBlock Margin="10 0 10 8" Foreground="#000">
                            <TextBlock.Text>
                                <Binding Path="HireDate" StringFormat="{}Hired on {0:MMM dd, yyyy}"/>
                            </TextBlock.Text>
                        </TextBlock>
                    </StackPanel>
                </Border>
            </Border>
        </DataTemplate>

        <Style TargetType="{x:Type ListBoxItem}" x:Key="CustomerItemContainerStyle">
            <Setter Property="ContentTemplate" Value="{StaticResource CustomerItemTemplate}" />
            <Setter Property="Padding" Value="0"/>
            <Setter Property="Margin" Value="0" />
            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="ContentTemplate" Value="{StaticResource CustomerItemTemplateSelected}" />
                </Trigger>
            </Style.Triggers>
        </Style>

    </Window.Resources>

    <ScrollViewer>
    <DockPanel LastChildFill="False" Margin="10">

        <ContentControl
            DockPanel.Dock="Top"
            Margin="0 0 0 10"
            Content="{Binding SelectedCustomer}"
            ContentTemplate="{StaticResource CustomerShowTemplate}"/>

        <StackPanel
            HorizontalAlignment="Left"
            DockPanel.Dock="Top"
            Margin="0 0 0 10">

            <ComboBox
                ItemsSource="{Binding Customers}"
                ItemTemplate="{StaticResource CustomerComboBoxTemplate}"
                Margin="10"
                HorizontalAlignment="Left"
                SelectedItem="{Binding SelectedCustomer, Mode=TwoWay}"/>

            <Slider Minimum="0"
                    Margin="10"
                    Width="400"
                    IsSnapToTickEnabled="True"
                    Maximum="{Binding HighestCustomerIndex, Mode=TwoWay}"
                    Value="{Binding SelectedCustomerIndex, Mode=TwoWay}"/>

            <StackPanel Orientation="Horizontal"
                        Margin="10">
                <TextBlock Text="Type in a new customer name: "
                             FontSize="14"/>
                <TextBox
                    Width="150"
                    Text="{Binding NewFirstName}"/>
                <TextBlock Text=" "/>
                <TextBox
                    Width="150"
                    Text="{Binding NewLastName}"/>
                <TextBlock Text=" "/>
                <Button
                    Width="150"
                    HorizontalAlignment="Left"
                    Content="Add Customer"
                    Command="{Binding AddCustomerCommand}"/>
            </StackPanel>

            <ListBox HorizontalAlignment="Left"
                ItemsSource="{Binding Customers, Mode=TwoWay}"
                ItemContainerStyle="{StaticResource CustomerItemContainerStyle}"
                SelectedItem="{Binding SelectedCustomer, Mode=TwoWay}"/>

        </StackPanel>

    </DockPanel>
    </ScrollViewer>
</Window>
post comment
 
WPF CODE EXAMPLE created on Friday, June 19, 2009 permalink
Three ways to format dates in a XAML DataTemplate
Just wanted to record these three ways of formatting dates, basically you can use StringFormat in the same way you do in code in this way, also see my example of MultiBinding which uses StringFormat.
<Window x:Class="TestSelectedItem234.Views.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:c="clr-namespace:TestSelectedItem234.Commands"
    Title="Main Window" Height="400" Width="800">

    <Window.Resources>
        <DataTemplate x:Key="CustomerShowTemplate">
            <Border CornerRadius="5"
                    Background="#eee"
                    Padding="5"
                    HorizontalAlignment="Left"
                    Width="200">
                <StackPanel>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock FontSize="14" FontWeight="Bold" Text="{Binding FirstName}"/>
                        <TextBlock Text=" "/>
                        <TextBlock FontSize="14" FontWeight="Bold" Text="{Binding LastName}"/>
                    </StackPanel>
                    <TextBlock Text="{Binding Path=HireDate,
                        StringFormat='MMM dd, yyyy'}"/>
                    <TextBlock Text="{Binding Path=HireDate,
                        StringFormat='Hired on {0}'}"/>
                    <TextBlock Text="{Binding Path=HireDate,
                        StringFormat='Hired on {0:MMM dd, yyyy}'}"/>
                </StackPanel>
            </Border>
        </DataTemplate>
    </Window.Resources>

    <DockPanel LastChildFill="False" Margin="10">

        <ContentControl
            DockPanel.Dock="Top"
            Margin="0 0 0 10"
            Content="{Binding SelectedCustomer}"
            ContentTemplate="{StaticResource CustomerShowTemplate}"/>

    </DockPanel>
</Window>

post comment
 
WPF CODE EXAMPLE created on Thursday, June 18, 2009 permalink
How to access objects and their properties within Observable collections
This was an experiment to find the syntax to access e.g. a particular property of a particular customer within a collection and determine some UI effect based on the value. Notice you get the Status of the first customer object with this: {Binding Customers[0].Status}.
View:
<Window x:Class="TestMvvmProperties8383.Views.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:c="clr-namespace:TestMvvmProperties8383.Commands"
    Title="Main Window" Height="400" Width="800">
    <Window.Resources>
        <Style x:Key="MainMessage" TargetType="TextBlock">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Customers[0].Status}" Value="approved">
                    <Setter Property="Text" Value="First customer is approved"/>
                    <Setter Property="Background" Value="LightGreen"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding Customers[0].Status}" Value="waiting">
                    <Setter Property="Text" Value="First customer is waiting"/>
                    <Setter Property="Background" Value="Yellow"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>

        <DataTemplate x:Key="MainTemplate">
            <Border CornerRadius="5" Background="Orange" Padding="5" Margin="2">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding FirstName}"/>
                    <TextBlock Text=" "/>
                    <TextBlock Text="{Binding LastName}"/>
                    <TextBlock Text=": "/>
                    <TextBlock Text="{Binding Status}"/>
                </StackPanel>
            </Border>
        </DataTemplate>
    </Window.Resources>

    <DockPanel HorizontalAlignment="Left" LastChildFill="False" Margin="10">
        <TextBlock
            DockPanel.Dock="Top"
            Margin="10"
            Style="{StaticResource MainMessage}"/>
        <ItemsControl
            Margin="10"
            DockPanel.Dock="Top"
            ItemsSource="{Binding Customers}"
            ItemTemplate="{StaticResource MainTemplate}"/>

        <StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="10">
            <Button Content="Sort Order 1" Command="{Binding SortOrder1Command}" Margin="5"/>
            <Button Content="Sort Order 2" Command="{Binding SortOrder2Command}" Margin="5"/>
        </StackPanel>
    </DockPanel>
</Window>

ViewModel:
        public MainViewModel()
        {
            LoadCustomers(1);
        }

        private void LoadCustomers(int sortOrder)
        {
            Customers.Clear();

            if (sortOrder == 1)
            {
                Customers.Add(new Customer { FirstName = "Jim", LastName = "Smith", Status = "waiting" });
                Customers.Add(new Customer { FirstName = "Joe", LastName = "Jones", Status = "waiting" });
                Customers.Add(new Customer { FirstName = "Jack", LastName = "Alard", Status = "approved" });
            }
            else
            {
                Customers.Add(new Customer { FirstName = "Jack", LastName = "Alard", Status = "approved" });
                Customers.Add(new Customer { FirstName = "Jim", LastName = "Smith", Status = "waiting" });
                Customers.Add(new Customer { FirstName = "Joe", LastName = "Jones", Status = "waiting" });
            }
        }
post comment
 
WPF CODE EXAMPLE created on Thursday, June 18, 2009 permalink
How to access bound individual items in ObservableCollection from XAML
This shows an example of an instant translator for an application: a user can use a slider to switch between English and German whereby he instantly sees the text on every control be translated. Collection elements such as ListView are straight-forward and for single elements such as Button and TextBlock the syntax for accessing the desired object is {Binding Translations[0].Value} where "Value" can be any property on the object in the ObservableCollection.
XAML:
<Window x:Class="TestObjectUpdate234.Views.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:c="clr-namespace:TestObjectUpdate234.Commands"
    Title="Main Window" Height="250" Width="600">
    
    <Window.Resources>
        <DataTemplate x:Key="ShowTemplate">
            <TextBlock Text="{Binding Value}"/>
        </DataTemplate>
    </Window.Resources>
    
    <DockPanel LastChildFill="False" Margin="10">

        <Button DockPanel.Dock="Top"
                Content="{Binding Translations[0].Value}"
                Width="150"
                Margin="5"
                HorizontalAlignment="Left"/>
        <TextBlock
            DockPanel.Dock="Top"
            Margin="5"
            Text="{Binding Translations[1].Value}" />
        
        <ListView
            DockPanel.Dock="Top"
            ItemsSource="{Binding Translations}"
            Margin="5"
            ItemTemplate="{StaticResource ShowTemplate}"/>

        <StackPanel
            DockPanel.Dock="Bottom"    
            Orientation="Horizontal"
            Margin="0 20 0 0">
            
            <TextBlock Text="English" Margin="0 0 5 0"/>
            <Slider Name="TheLanguageIndexSlider"
                
                Minimum="0"
                Maximum="1"
                IsSnapToTickEnabled="True"
                Width="100"
                Margin="5"
                Value="{Binding LanguageIndex}"
                HorizontalAlignment="Left"/>
            <TextBlock Text="German" Margin="5 0 0 0"/>
        </StackPanel>
        
    </DockPanel>
</Window>

ViewModel:
using System.Collections.Generic;
using System.Collections.ObjectModel;
using TestObjectUpdate234.Models;

namespace TestObjectUpdate234.ViewModels
{
    public class MainViewModel : ViewModelBase
    {

        private ObservableCollection<TranslateTerm> _translations = new ObservableCollection<TranslateTerm>();
        public ObservableCollection<TranslateTerm> Translations
        {
            get
            {
                return _translations;
            }

            set
            {
                _translations = value;
                OnPropertyChanged("Translations");
            }
        }

        private int _languageIndex;
        public int LanguageIndex
        {
            get
            {
                return _languageIndex;
            }

            set
            {
                _languageIndex = value;
                OnPropertyChanged("LanguageIndex");
                FillTranslations();
            }
        }

        public MainViewModel()
        {
            _languageIndex = 0; //english
            FillTranslations();
        }

        private void FillTranslations()
        {
            if (_languageIndex == 0)
            {
                Translations.Clear();
                Translations.Add(new TranslateTerm { Key = "add", Value = "Add"});
                Translations.Add(new TranslateTerm { Key = "copy", Value = "Copy" });
            }
            else
            {
                Translations.Clear();
                Translations.Add(new TranslateTerm { Key = "add", Value = "Hinzufügen" });
                Translations.Add(new TranslateTerm { Key = "copy", Value = "Kopieren" });
            }

        }

    }
}

TranslateTerm.cs:
namespace TestObjectUpdate234.Models
{
    public class TranslateTerm
    {
        public string Key { get; set; }
        public string Value { get; set; }
    }
}
post comment
 
WPF CODE EXAMPLE created on Thursday, June 18, 2009 permalink
How to access items in a (readonly) ViewModel Dictionary property
This example shows how you can have a ViewModel property that is a Dictionary of saw 200 items and in your view you can access each one with simple square bracket syntax.    Unfortunately the Dictionary object is not updated as are string properties as this example shows. So this is a good solution if you need a readonly Dictionary that does not need to be further updated at runtime. For that, you would need to create an ObservableDictionary or find some syntax like this which allows you to access items in an ObservableCollection in the same way as you access them in a Dictionary.
XAML:
<Window x:Class="TestObjectUpdate234.Views.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:c="clr-namespace:TestObjectUpdate234.Commands"
    Title="Main Window" Height="400" Width="800">
    <StackPanel Margin="10">

        <TextBlock Text="{Binding TranslationEdit}" />
        <TextBlock Text="{Binding Translations[add]}" />

        <StackPanel DockPanel.Dock="Bottom"    Orientation="Horizontal" Margin="0 20 0 0">
            <TextBlock Text="English" Margin="0 0 5 0"/>
            <Slider Name="TheLanguageIndexSlider"
                
                Minimum="0"
                Maximum="1"
                IsSnapToTickEnabled="True"
                Width="100"
                Margin="5"
                Value="{Binding LanguageIndex}"
                HorizontalAlignment="Left"/>
            <TextBlock Text="German" Margin="5 0 0 0"/>
        </StackPanel>

    </StackPanel>
</Window>

ViewModel:
using System.Collections.Generic;

namespace TestObjectUpdate234.ViewModels
{
    public class MainViewModel : ViewModelBase
    {
        
        private string _translationEdit;
        public string TranslationEdit
        {
            get
            {
                return _translationEdit;
            }

            set
            {
                _translationEdit = value;
                OnPropertyChanged("TranslationEdit");
            }
        }

        private Dictionary<string, string> _translations = new Dictionary<string, string>();
        public Dictionary<string, string> Translations
        {
            get
            {
                return _translations;
            }

            set
            {
                _translations = value;
                OnPropertyChanged("Translations");
            }
        }

        private int _languageIndex;
        public int LanguageIndex
        {
            get
            {
                return _languageIndex;
            }

            set
            {
                _languageIndex = value;
                OnPropertyChanged("LanguageIndex");
                FillTranslations();
            }
        }

        public MainViewModel()
        {
            _languageIndex = 0; //english
            FillTranslations();

        }

        private void FillTranslations()
        {
            if (_languageIndex == 0)
            {
                TranslationEdit = "Edit";

                Translations.Clear();
                Translations.Add("add", "Add");
            }
            else
            {
                TranslationEdit = "Bearbeiten";

                Translations.Clear();
                Translations.Add("add", "Hinzufügen");
            }

        }


    }
}
post comment
 
C# CODE EXAMPLE created on Wednesday, June 17, 2009 permalink
How to get and set properties of an object dynamically with reflection
These two methods can be used on on object so that you can e.g. parse an XML file that has changes in it, and make changes on an object based on the strings in the XML file.
using System;
using System.Reflection;

namespace TestSetPropertyValue834
{
    class Program
    {
        static void Main(string[] args)
        {
            Customer customer = new Customer { Id = 1, FirstName = "Jim", LastName = "Smith" };

            Console.WriteLine(customer.LastName);
            Console.WriteLine(customer.GetPropertyValueAsString("LastName"));
            customer.SetPropertyValueWithString("LastName", "SmithChanged");
            Console.WriteLine(customer.GetPropertyValueAsString("LastName"));
            Console.ReadLine();
        }
    }

    class Customer
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Age { get; set; }

        public string GetPropertyValueAsString(string propertyName)
        {
            PropertyInfo prop = typeof(Customer).GetProperty(propertyName);
            object value = prop.GetValue(this, null);
            return value.ToString();
        }

        public void SetPropertyValueWithString(string propertyName, string value)
        {
            PropertyInfo prop = typeof(Customer).GetProperty(propertyName);
            prop.SetValue(this, value, null);
        }
    }
}
post comment