MVVM + UserControl + UserControl + DependencyProperty - PullRequest
0 голосов
/ 10 февраля 2012

У меня есть пользовательский элемент управления, который отображает адреса, размещенные внутри другой страницы, связанной с моделью представления. Модель представления имеет примитив Пользователь , который имеет коллекцию Адрес объектов. Пользовательский элемент управления будет находиться на нескольких страницах, поэтому я хотел бы иметь возможность привязать его к списку адресов через свойство зависимости. В то время как мое текущее решение работает, что-то об этом просто кажется неправильным, и я подумал, что я бы попросил другое мнение. Ради краткости я вырубил много кода.

По сути, страница привязывается к свойству зависимости в коде usercontrols, за которым затем обновляет сетку данных usercontrol, устанавливая ее источник элементов. Мне кажется, это нарушает основных арендаторов MVVM.

Элемент управления AddressListView:

<UserControl x:Class="Insight.Controls.AddressListView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
    xmlns:tk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"
    xmlns:command="clr-namespace:PrismFramework.Implementors.Commanding;assembly=PrismFramework"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="840">

    <UserControl.Resources>
        <command:ObservableCommand x:Name="EditAddressCommand" Value="{Binding EditAddressCmd}"/>
        <command:ObservableCommand x:Name="DeleteAddressCommand" Value="{Binding DeleteAddressCmd}"/>
    </UserControl.Resources>

    <Grid x:Name="LayoutRoot" Background="White">
        <sdk:DataGrid Name="dgAddresses" 
                    Height="Auto" 
                    Width="Auto" 
                    AutoGenerateColumns="False" 
                    HeadersVisibility="None" >
            <sdk:DataGrid.Columns>
                <sdk:DataGridTemplateColumn x:Name="dgcAddresses" 
                            Width="*" >
                    <sdk:DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Border x:Name="bdrAddress" 
                                    HorizontalAlignment="Stretch"
                                    VerticalAlignment="Stretch"
                                    Height="Auto"
                                    Width="Auto"
                                    BorderBrush="Silver"  
                                    BorderThickness="1" 
                                    Padding="0" 
                                    Margin="1,1,1,1">
                                <Grid x:Name="grdAddressItem"
                                        HorizontalAlignment="Stretch"
                                        VerticalAlignment="Stretch"
                                        Height="Auto" 
                                        Width="Auto">
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="17" MinHeight="17"/>
                                        <RowDefinition Height="17" MinHeight="17"/>
                                        <RowDefinition Height="17" MinHeight="17"/>
                                        <RowDefinition Height="17" MinHeight="17"/>
                                        <RowDefinition Height="17" MinHeight="17"/>
                                        <RowDefinition Height="17" MinHeight="17"/>
                                        <RowDefinition Height="17" MinHeight="17"/>
                                    </Grid.RowDefinitions>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="70"/>
                                        <ColumnDefinition Width="55" />
                                        <ColumnDefinition Width="*" />
                                        <ColumnDefinition Width="Auto" />
                                    </Grid.ColumnDefinitions>
                                    <TextBlock Padding="0,0,5,0" Text="Type:" TextAlignment="Right" />
                                    <TextBlock Grid.Column="1" Padding="0" Text="{Binding Path=AType}" Grid.ColumnSpan="2" />
                                    <TextBlock Grid.Row ="1" Grid.Column="0" Padding="0,0,5,0" Text="Address 1:" TextAlignment="Right" />
<!-- List Of Similar Fields ->
                                    <Grid x:Name="grdAddressEditOptions" 
                                            HorizontalAlignment="Stretch"
                                            VerticalAlignment="Stretch"
                                            Height="Auto"
                                            Width="Auto"
                                            Grid.Column="3"
                                            Grid.RowSpan="7" >
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="Auto" />
                                            <RowDefinition Height="*" />
                                            <RowDefinition Height="Auto" />
                                        </Grid.RowDefinitions>
                                        <Button x:Name="btnEdit"
                                                HorizontalAlignment="Stretch"
                                                VerticalAlignment="Stretch"
                                                Height="Auto"
                                                Width="Auto"
                                                Grid.Row="0"
                                                Padding="4,5,4,8"
                                                Margin="0,8,10,0"
                                                Command="{Binding Value, Source={StaticResource EditAddressCommand}}"
                                                CommandParameter="{Binding}" >
                                            <Button.Content>
                                                <Image x:Name="btnEditIcon"
                                                        HorizontalAlignment="Center"
                                                        VerticalAlignment="Center"
                                                        Height="Auto"
                                                        Width="Auto"
                                                        Source="/Insight.ModuleUser;component/Images/edit.png" 
                                                        Visibility="Visible" />
                                            </Button.Content>
                                        </Button>
                                        <Button x:Name="btnDelete"
                                                HorizontalAlignment="Stretch"
                                                VerticalAlignment="Stretch"
                                                Height="Auto"
                                                Width="Auto"
                                                Grid.Row="2"
                                                Padding="4,5,4,8"
                                                    Margin="0,0,10,5"
                                                Command="{Binding Value, Source={StaticResource  DeleteAddressCommand}}"
                                                CommandParameter="{Binding}" >
                                            <Button.Content>
                                                <Image x:Name="btnDeleteIcon"
                                                            HorizontalAlignment="Center"
                                                            VerticalAlignment="Center"
                                                            Height="Auto"
                                                            Width="Auto"
                                                            Source="/Insight.ModuleUser;component/Images/delete.png" 
                                                            Visibility="Visible" />
                                            </Button.Content>
                                        </Button>
                                    </Grid>
                                </Grid>
                            </Border>
                        </DataTemplate>
                    </sdk:DataGridTemplateColumn.CellTemplate>
                </sdk:DataGridTemplateColumn>
            </sdk:DataGrid.Columns>
        </sdk:DataGrid>
    </Grid>
</UserControl>

Код AddressListView позади:

Imports System.Collections.ObjectModel
Imports Insight.DataServices.Primitives

Partial Public Class AddressListView
Inherits UserControl

Public ReadOnly AddressesProperty As DependencyProperty = DependencyProperty.Register("Addresses", GetType(ObservableCollection(Of Address)), GetType(AddressListView), New PropertyMetadata(Nothing, New PropertyChangedCallback(AddressOf OnAddressesChanged)))

Public Sub New()
    InitializeComponent()
End Sub

Public Property Addresses As ObservableCollection(Of Address)
    Get
        Return DirectCast(GetValue(AddressesProperty), ObservableCollection(Of Address))
    End Get
    Set(value As ObservableCollection(Of Address))
        SetValue(AddressesProperty, value)
    End Set
End Property

Public Sub OnAddressesChanged()
    Me.dgAddresses.ItemsSource = Addresses
End Sub

End Class

Базовая страница:

<UserControl x:Class="Insight.ModuleUser.Views.EditUserView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"    
    xmlns:prism="clr-namespace:Microsoft.Practices.Prism.Interactivity.InteractionRequest;assembly=Microsoft.Practices.Prism.Interactivity"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"  
    xmlns:cm="clr-namespace:System.ComponentModel;assembly=System.Windows"
    xmlns:data="clr-namespace:System.Windows.Data;assembly=System.Windows"
    xmlns:vm="clr-namespace:Insight.ModuleUser.ViewModels"
    xmlns:command="clr-namespace:PrismFramework.Implementors.Commanding;assembly=PrismFramework"
    xmlns:controls="clr-namespace:Insight.Controls;assembly=Insight.Controls"
    xmlns:modalDialogs="clr-namespace:Insight.Controls.ModalDialogViews;assembly=Insight.Controls"
    mc:Ignorable="d"
    d:DesignHeight="500" d:DesignWidth="1144" 
    d:DataContext="{d:DesignData /Insight.ModuleUser;component/SampleData/EditUserViewModelSampleData.xaml}">

    <UserControl.Resources>
        <command:ObservableCommand x:Name="OpenProjectCommand" Value="{Binding OpenProjectCmd}"/>
        <command:ObservableCommand x:Name="OpenPaymentCommand" Value="{Binding OpenPaymentCmd}"/>
        <command:ObservableCommand x:Name="OpenInvoiceCommand" Value="{Binding OpenInvoiceCmd}"/>
        <command:ObservableCommand x:Name="OpenPaymentItemCommand" Value="{Binding OpenPaymentItemCmd}"/>

        <command:ObservableCommand x:Name="EditPhoneCommand" Value="{Binding EditPhoneNumberCmd}"/>
        <command:ObservableCommand x:Name="DeletePhoneCommand" Value="{Binding DeletePhoneNumberCmd}"/>
        <command:ObservableCommand x:Name="EditEmailAddressCommand" Value="{Binding EditEmailAddressCmd}"/>
        <command:ObservableCommand x:Name="DeleteEmailAddressCommand" Value="{Binding DeleteEmailAddressCmd}"/>

    </UserControl.Resources>

    <Grid x:Name="LayoutRoot" >


                <controls:AddressListView x:Name="ctrlAddressListView" 
                    Addresses="{Binding User.Addresses}" />

    </Grid>
</UserControl>

1 Ответ

1 голос
/ 10 февраля 2012

Это кажется вполне разумным подходом.Однако вы можете использовать привязку в представлении управления пользователем, а не указывать источник элементов в коде.

Для этого вам нужно установить DataContext пользовательского элемента управления в качестве вашего пользовательского элемента управления.Это можно сделать либо в коде для пользовательского элемента управления (настройка this.DataContext = this), либо с помощью привязки элемента в XAML:

<UserControl
...
 x:Name="MyName"
 DataContext="{Binding ElementName=MyName}"

Однако мой подход заключается в том, чтобы вообще не использовать пользовательский элемент управления, поскольку все, о чем вы на самом деле говорите, - это состав представления и повторное использование определенного раздела представления между другими представлениями.

Состав представления очень прост с использованием инфраструктуры MVVM, например Caliburn.Micro ,В этом случае у вас будут AddressViewModel и AddressView, и вы будете использовать ContentControl для ввода AddressView в базовый вид:

<ContentControl x:Name="AddressViewModel" />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...