简体   繁体   中英

creating a reusable user control in WPF

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,

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>

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM