views:

39

answers:

3

I'd like to create a simple custom panel to layout children in a business form fashion. Ideally I'd like my markup to look like this:

<Panels:FormPanel>
        <TextBlock Text="Name:"/>
        <TextBox />
        <TextBlock Text="Address"/>
        <TextBlock Text="Unknown"/>
        <TextBlock  Text="City"/>
        <TextBox HorizontalAlignment="Stretch"/>
        <TextBlock Text="State"/>
        <ComboBox/>
        <TextBlock  Text="Country"/>
        <StackPanel>...</StackPanel>
 </Panels:FormPanel>

The panel will layout controls in two columns labels on the left side and values on the right. I have no problem laying out my controls. The problem is that I also need to alternate background for the rows to create stripes for easier reading. Any ideas how can this be done?

A: 

This doesn't directly answer your question, but you could consider this as another solution to the underlying problem.

Take a look at http://wpg.codeplex.com/. I used a similar property-grid-like control in Windows Forms that was modified to understand custom attributes on my business objects.

Now, in WPF, I would think something similar would work really well if you follow the MVVM pattern and you decorate your ViewModel with attributes that such a property grid understands. Then you don't need to explicitly define the fields like you show above.

You could have a ViewModel:

class PersonViewModel
{
    [DisplayName("Name")] // The property Grid uses this the Textblock text
    [IsRequired] // The property grid could do validation on the field
    [Visible]
    public string Name { get; set; }

    public long InvisibleSystemField { get; set; } // Not shown
}

And then you'd only have Views (Xaml files) like this:

<myCommon:PropertyGrid DataContext={Binding}/>

It could simply use it's DataContext as the starting point for reflection.

OK I'll stop there for now :)

I'm working on a WPF powered LOB application and I'll possibly build something like this in future.

Andre Luus
A: 

Andre, Thanks for your answer! You're right property grid is kinda what I'm trying to build. And yes, I'm using MVVM pattern. This is not helping with my background problem though. At least I can't see how.

I'm thinking that it is not responsibility of a panel to set the background. Panel could set the attached property - something like IsOdd or RowIndex to their children. I can create custom control (somehow similar to ItemsControl) that can use this panel internally to layout it's children. The control can apply template that can set backgrounds. Not sure if that is the right approach.

Maxim
A: 

Implementing a custom panel is not actually that difficult. You have to override two methods, Measure and Arrange. Google for "wpf custom panel" to get some articles about that.

What I would suggest you do to get the behavior exactly as you required in the question is extend Windows.Controls.Grid. Your custom grid could then have two columns by default that you initialize in the constructor and you can programmatically set the Grid.Column and Grid.Row properties on the child controls.

Also worth looking at could be the ItemsControl. It does have support for alternatively colored rows. This example (from MSDN) shows how to use it:

<Grid>
  <Grid.Resources>
    <Style x:Key="alternatingWithTriggers" TargetType="{x:Type ListBoxItem}">
      <Setter Property="Background" Value="Blue"/>
      <Setter Property="Foreground" Value="White"/>
      <Style.Triggers>
        <Trigger Property="ListBox.AlternationIndex" Value="1">
          <Setter Property="Background" Value="CornflowerBlue"/>
          <Setter Property="Foreground" Value="Black"/>
        </Trigger>
        <Trigger Property="ListBox.AlternationIndex" Value="2">
          <Setter Property="Background" Value="LightBlue"/>
          <Setter Property="Foreground" Value="Navy"/>
        </Trigger>
      </Style.Triggers>
    </Style>

  </Grid.Resources>
  <ListBox AlternationCount="3" ItemsSource="{StaticResource data}" 
           ItemContainerStyle="{StaticResource alternatingWithTriggers}">
  </ListBox>
</Grid>

You could then specify a template for the items that includes a Label and a TextBox, but getting this to work could be fiddly.

Here's one final thing I'll suggest:

XAML Powertoys include features that allow you to generate business forms from ViewModels, ViewModels from Models and much more. You might need to modify the source to get alternating row colors though.

Good luck!

Andre Luus