views:

492

answers:

3

I have a very simple case that I think would benefit from using templates (but I'm not sure, which is why I'm asking). All the templating examples I've seen either assume more knowledge than I have, are too specific to be of much use to a total newb like myself, or contain lots of ancillary stuff that makes it hard to identify what's part of the template.

Here's the setup: I have two labels side-by-side, with the first label populated with the name of a field, and the second label populated with the value of the field.

Here is the XAML I currently have in my app (many, many times):

<StackPanel Style="{StaticResource horizontalStackerStyle}">
    <Label Style="{StaticResource labelStyle}">Field One:</Label>
    <Label Style="{StaticResource valueStyle}" Name="field1" 
        Content="{Binding dataObject.field1}" />
</StackPanel>

I would like to create a template such that I could write XAML like this:

<CustomControlOrWhatever 
    FieldName="Field One:" 
    FieldValue="{Binding dataObject.field1}"/>

I have a feeling I can do this with some kind of template. One benefit of which would be that I don't need to keep specifying the styles over and over. Am I correct? How would I do this?

Thanks in advance!

UPDATE:

Still haven't found an answer to this. I chose a possible solution using Dependency Properties, and tried to ask a clarifying question here. Well, the first responder said that I don't actually need to clutter up my code behind with DP nonsense, so I changed it again--and it still doesn't work. Can anyone come up with a working solution? This seems like it should be so simple.

Just to be clear: this only needs to be one-way binding with values updated every few seconds.

+2  A: 

What you're asking for is basically a user control.

<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SomeNameSpace.SomeControlName">
    <Grid x:Name="LayoutRoot">
     <StackPanel Style="{StaticResource horizontalStackerStyle}">
      <Label Style="{StaticResource labelStyle}" x:Name="FieldNameLbl"></Label>
      <Label Style="{StaticResource valueStyle}" x:Name="ValueLbl">
      </StackPanel>
    </Grid>
</UserControl>

In the code behind, you'd need to expose two properties that would set the value of the controls.

public string FieldName
{
    get { return FieldNameLbl.Text; }
    set { FieldNameLbl.Text = value; }
}

public string FieldValue
{
    get { return ValueLbl.Text; }
    set { ValueLbl.Text = value; }
}

And then to call that you can put this at the top of your window/page with the rest of your declarations:

xmlns:Controls="clr-namespace:SomeNameSpace"

and then you can insert the control into your window/page like this:

<Controls:NameOfYourControl FieldName="Field One:" FieldValue="{Binding dataObject.field1}"/>
Brandon
Thanks for the thorough response!
Klay
+1, sometimes nice to make the CLR properties dependency properties.
sixlettervariables
It's apparently totally necessary to make these dependency properties. This field is updated every few seconds with values from a serial port connection. So I'm trying to bind the fieldValue to a property on my business object, but I can't seem to get the dependency property stuff to work.Is this the appropriate way to ask follow up questions, or do I need to start a new question?
Klay
I would start a new question. Your original question was how to make a tmeplate, which is answered by my response.Continuously updating a DP warrants a new question.
Brandon
+1  A: 

You could create a UserControl called FieldControl and define backing (automatic) properties for FieldName and FieldValue. (Normal properties would be fine, so long as you only need to bind once, which is probably the case.)

The XAML code might look like:

<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             x:Class="foo.bar">
    <StackPanel Style="{StaticResource horizontalStackerStyle}">
        <Label Style="{StaticResource labelStyle}" Content="{Binding Path=FieldName, Mode=OneTime, StringFormat='{0}: '}"/>
        <Label Style="{StaticResource valueStyle}" Content="{Binding Path=FieldValue, Mode=OneTime}" />
    </StackPanel>
</UserControl>

Hope that helps.

Noldorin
Thank you, it does!
Klay
Not enough for an up-vote though?
Noldorin
Apparently I don't have enough reputation for an up vote.But to more thoroughly answer you:It helped me see the form of the XAML, which is a start. But I'm discovering that to make this UserControl useful, I need to set up dependency properties and figure out how to bind everything. So far, no luck.
Klay
Klay: Sorry, my bad - I forget these things at my rep! Well I'm glad it's helped you understand things at least. +1 to your question.
Noldorin
A: 

What you want to do is similar to the discussion about putting images on a button with a simple way of specifying the path, like <Button MyImage="foo.jpg" />. Follow this article for the actual details.

To summarize:

  • One obvious way would be to create an UserControl containing your two labels and exposing the two properties. Not much templating here.

  • The most WPFish solution seems to be to use two Attached Properties on one of the labels (say the value), and provide a control template for it that includes the other label (the description). In the template, you bind each label text to the corresponding attached property value.

Tiberiu Ana