2

In the (fairly large) LOB application we are building with WPF for UI we have a lot of viewmodels that contain the same kind of data sub-object. For example, there are a lot of addresses

public class AddressViewModel : INotifyPropertyChanged
{

   public string City {...}
   public string ZipCode {...}
   public string Address {...}
   public string Number {...}

  // INPC logic omitted 
}

scattered among business objects:

public class CustomerViewModel : INotifyPropertyChanged
{
     public string Name {...}
     public AddressViewModel BillingAddress {...}
     public AddressViewModel DeliveryAddress {...}
     /*
     ...
     */
}

is it possible to build a reusable custom User Control which we can bind to any address sub-object?

In a view (possibly another custom user control) designed to edit customer details we would like to put a custom control like this

<UserControl x:Class="OurApp.View.AddressEditor"
             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">
    <Grid>

        <TextBox x:Name="ZipCode" Text="{Binding Path=ZipCode, UpdateSourceTrigger = PropertyChanged}" Validation.ErrorTemplate="{x:Null}" HorizontalAlignment="Left" Height="23" Margin="10,19,0,0" TextWrapping="Wrap"  VerticalAlignment="Top" Width="120" />

         <!-- other fields for the rest of AddressViewModel properties-->

    </Grid>

</UserControl>

that we can simply use like this in a view bound to a CustomerViewModel instance

 <TextBox x:Name="Name" Text="{Binding Path=Name, UpdateSourceTrigger = PropertyChanged}" Validation.ErrorTemplate="{x:Null}" />

<AddressEditor SomeProperty="{something that points to BillingAddress}" />
<AddressEditor SomeProperty="{something that points to DeliveryAddress}" />

What is the correct way to do this? We tried to point the binding to BillingAddress but we did not find a working way...

Thanks in advance for any contribution,

2 Answers 2

8

Yeah that should be very easy, either create a lookless control with DataTemplate, or just create a standard UserControl. Trick it to set its DataContext to a full Address object

<local:AddressControl DataContext="{Binding BillingAddress}"/>

Which would allow your new "AddressControl" to have markup something like this

<StackPanel Orientation="Vertical">
<Label Content="City"/>
<TextBox Content="{Binding City}"/>

<Label Content="ZipCode"/>
<TextBox Content="{Binding ZipCode}"/>

<Label Content="ZipCode"/>
<TextBox Content="{Binding ZipCode}"/>

<Label Content="Number"/>
<TextBox Content="{Binding Number}"/>
</StackPanel>
Sign up to request clarification or add additional context in comments.

2 Comments

Actually this is the same method I tried first before asking here but it did not work because in my experimental code BillingAddress and DeliveryAddress where members and not properties (my fault), I was a bit surprised I could not get WPF to work in this simple case :) Now it is working!
This is the best solution so far of all 50 pages I've searched on how to - thanks
0

you can set the datacontext for your adresseditor to eg. the BillingAddress it should work as long the billingaddress has the properties you need in your usercontrol

<TextBox x:Name="Name" Text="{Binding Path=Name, UpdateSourceTrigger = PropertyChanged}" Validation.ErrorTemplate="{x:Null}" />
<AddressEditor DataContext="{Binding Path=BillingAddress}" />

instead of setting the datacontext its also possible to create a dependency property for your usercontrol where you can bind your BillingAddress to.

1 Comment

Actually this is the same method I tried first before asking here but it did not work because in my experimental code BillingAddress and DeliveryAddress where members and not properties (my fault), I was a bit surprised I could not get WPF to work in this simple case :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.