Reputation: 13778
I'm developing a WPF user control and I want it to display some design-time data. It's proving to be quite a challenge to get things just right and I could really use your help.
Here's my control so far, basically a <ListBox>
:
<UserControl x:Class="TA.Weather.UI.Wpf.WorkingSetEditor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Loaded="HandleLoadedEvent"
>
<Grid d:DataContext="{d:DesignData Source=/SampleData/WorkingSet.xaml}">
<ListBox x:Name="WorkingSetListBox" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="30" />
<ColumnDefinition MinWidth="30" />
<ColumnDefinition MinWidth="30" />
<ColumnDefinition MinWidth="30" />
<ColumnDefinition MinWidth="30" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" TextAlignment="Center"
Text="{Binding Path=[0].Limits.StationId}"></TextBlock>
<TextBlock Grid.Column="1" TextAlignment="Center"
Text="{Binding Path=[0].Limits.SensorId}"></TextBlock>
<TextBlock Grid.Column="2" TextAlignment="Center"
Text="{Binding Path=[0].Limits.SensorName}"></TextBlock>
<TextBlock Grid.Column="3" TextAlignment="Center"
Text="{Binding Path=[0].Limits.LowerLimit}"></TextBlock>
<TextBlock Grid.Column="4" TextAlignment="Center"
Text="{Binding Path=[0].Limits.UpperLimit}"></TextBlock>
<CheckBox Grid.Column="5" x:Name="MonitoredCheckBox"
IsChecked="{Binding Path=[1].Monitored}"/>
</Grid>
</ListBox>
</Grid>
</UserControl>
I figured out how to create the design-time data in another XAML file, and set the build action to DesignDataWithDesignTimeCreatableTypes
. The type is essentially just a DTO so it seems OK to create instances at design time. So here's the data file, containing an List<SensorState>
with two members:
<generic:List x:TypeArguments="ws:SensorState"
xmlns:ws="clr-namespace:TA.Weather.Core;assembly=TA.Weather.Core"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:generic="clr-namespace:System.Collections.Generic;assembly=mscorlib">
<ws:SensorState IdleTimeout="300" LastUpdate="2015-08-19T03:39:00.000Z" Monitored="False"
WithinAcceptableLimits="False">
<ws:SensorState.Limits>
<ws:SensorLimits StationId="12-34-56-78-90-12" SensorId="1" SensorName="Inside Temperature"
LowerLimit="-10" UpperLimit="30" />
</ws:SensorState.Limits>
</ws:SensorState>
<ws:SensorState IdleTimeout="300" LastUpdate="2015-08-19T03:39:00.000Z" Monitored="True"
WithinAcceptableLimits="False">
<ws:SensorState.Limits>
<ws:SensorLimits StationId="12-34-56-78-90-12" SensorId="1" SensorName="Inside Temperature"
LowerLimit="-10" UpperLimit="30" />
</ws:SensorState.Limits>
</ws:SensorState>
</generic:List>
Thus far, this gets me a user control that looks like this:
So, success of sorts. However, there are two questions at this point:
There's more. I want to use a DataTemplate
to create a nicer look for the data; a bit later on there is going to be a slider control for setting the limits, etc. so here's how I've tried to use a template:
<UserControl x:Class="TA.Weather.UI.Wpf.WorkingSetEditor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:core="clr-namespace:TA.Weather.Core;assembly=TA.Weather.Core"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Loaded="HandleLoadedEvent"
>
<Grid d:DataContext="{d:DesignData Source=/SampleData/WorkingSet.xaml}">
<Grid.Resources>
<DataTemplate x:Key="WorkingSetTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="30" />
<ColumnDefinition MinWidth="30" />
<ColumnDefinition MinWidth="30" />
<ColumnDefinition MinWidth="30" />
<ColumnDefinition MinWidth="30" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" TextAlignment="Center"
Text="{Binding Path=[0].Limits.StationId}"></TextBlock>
<TextBlock Grid.Column="1" TextAlignment="Center"
Text="{Binding Path=[0].Limits.SensorId}"></TextBlock>
<TextBlock Grid.Column="2" TextAlignment="Center"
Text="{Binding Path=[0].Limits.SensorName}"></TextBlock>
<TextBlock Grid.Column="3" TextAlignment="Center"
Text="{Binding Path=[0].Limits.LowerLimit}"></TextBlock>
<TextBlock Grid.Column="4" TextAlignment="Center"
Text="{Binding Path=[0].Limits.UpperLimit}"></TextBlock>
<CheckBox Grid.Column="5" x:Name="MonitoredCheckBox"
IsChecked="{Binding Path=[1].Monitored}"/>
</Grid>
</DataTemplate>
</Grid.Resources>
<ListBox x:Name="WorkingSetListBox" ItemTemplate="{DynamicResource WorkingSetTemplate}">
</ListBox>
</Grid>
</UserControl>
So basically, I've moved the <Grid>
out of the <ListBox>
and into the <DataTemplate>
resource. As soon as I do this, the design-time data vanishes and I'm left with just a blank control in the designer. So my third question becomes:
<DataTemplate>
? What do I need to do differently?You can probably tell that I have almost no experience with WPF... I must admit I am struggling with binding expressions a little bit, they seem like some sort of arcane magic with little rhyme or reason to them. I think maybe I'm missing an important concept somewhere. I hope you can give me a few wise words to push me in the right direction.
Upvotes: 0
Views: 511