Question

I am wondering, which is the best and quickest way to get the well known Label Input [or output, doesn't matter] combination in WPF. Its a simple Task, just think of a quick output of the "object" ME:


Name - Christian

Age - 28

Mood - Good


I know, I can use a Grid with TextBlocks. But to be honest, the "short" XAML for this is nearly half a page long (RowDefinitions, ColDefs, Grid.Col on each Label)

The alternative way, using three StackPanels (horizontal) with one vertical seems also a little bit stupid. In this case, I have to give each Label a fixed width, to get the indent correct. And it just does not "feel" right.

So, given the Situation above, you got a custom object with 3-6 Properties you just want to dump as readonly to your GUI, how would you do it (in WPF, Silverlight too, if you are really in the mood :).

I can, of course, write a usercontrol for this. But why reinvent the wheel, if it might be already there...

And finally, to illustrate even further, the example I just created in real life and was the reason for this post:

      <StackPanel>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="Log Count"  Width="100"/>
            <TextBlock Text="{Binding LastLogRun.LogMessageCount}"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="Start Time" Width="100"/>
            <TextBlock Text="{Binding LastLogRun.StartTime}"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="End Time" Width="100"/>
            <TextBlock Text="{Binding LastLogRun.EndTime}"/>
        </StackPanel>
    </StackPanel>
Was it helpful?

Solution

If you're using 3.5sp1 you can use StringFormat in the binding. Something like this should work...

<TextBlock Text="{Binding LastLogRun.LogMessageCount, StringFormat={}Log Count - {0}}" />

OTHER TIPS

Perhaps you should rethink your UI. Why would you want Label - Textbox on the same line? That's a horrendous waste of space.

Why not Label over texbox? Then you've got a simple UI and simple XAML:

<StackPanel Orientation="Vertical">
  <TextBlock>Name</TextBlock>
  <TextBox />
  <TextBlock>Age</TextBlock>
  <TextBox />
  <TextBlock>Mood</TextBlock>
  <TextBox />
</StackPanel>

Add some styling for your TextBlocks and you've got a nice, clean UI, with very little repetition.

You could use shared size groups to get the auto-sizing Grid behavior of two nicely-lined-up columns, while still being able to pull out the complexity into a UserControl.

Here's an example of using a LabeledEdit control that would do what you're looking for. The complexity has all been factored away into the UserControl, and all you need to do is remember to set Grid.IsSharedSizeScope on the StackPanel:

<Window x:Class="WpfApplication5.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication5"
        Name="Self" Title="Window1" Height="300" Width="300">
    <StackPanel Grid.IsSharedSizeScope="True">
        <local:LabeledEdit Label="Name"/>
        <local:LabeledEdit Label="Age" Text="28"/>
        <!-- and with databinding... -->
        <local:LabeledEdit Label="Width"
                           Text="{Binding Width, ElementName=Self}"/>
        <local:LabeledEdit Label="Height"
                           Text="{Binding Height, ElementName=Self}"/>
    </StackPanel>
</Window>

And here's the source code for the UserControl. LabeledEdit.xaml:

<UserControl x:Class="WpfApplication5.LabeledEdit"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             Name="Self">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" SharedSizeGroup="LabeledEdit_Labels"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Label Grid.Column="0" Content="{Binding Label, ElementName=Self}"/>
        <TextBox Grid.Column="1" Text="{Binding Text, ElementName=Self}"/>
    </Grid>
</UserControl>

LabeledEdit.xaml.cs:

using System.Windows;

namespace WpfApplication5
{
    public partial class LabeledEdit
    {
        public static readonly DependencyProperty LabelProperty =
            DependencyProperty.Register("Label", typeof(object), typeof(LabeledEdit));
        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof(string), typeof(LabeledEdit),
            new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

        public LabeledEdit()
        {
            InitializeComponent();
        }

        public object Label
        {
            get { return GetValue(LabelProperty); }
            set { SetValue(LabelProperty, value); }
        }
        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }
    }
}

The silverlight toolkit has a DataForm control that works pretty cool!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top