2012-02-09 110 views
0

我有一個用戶控件,它顯示了綁定到視圖模型的另一個頁面內的地址。視圖模型具有原始的用戶其具有地址對象的集合。用戶控件將駐留在多個頁面上,因此我希望能夠通過依賴屬性將它綁定到地址列表。雖然我目前的解決方案正在工作,但有關它的一些問題只是感覺不對,我想我會要求第二個意見。爲了簡潔起見,我已經剔除了很多代碼。MVVM +用戶控件+用戶控件+ DependencyProperty

基本上,頁面綁定到usercontrols代碼中的依賴項屬性,然後通過設置它的itemsource來更新usercontrol的datagrid。這似乎打破了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

這似乎是一個完全合理的做法。但是,您可以在用戶控件視圖中使用綁定,而不是在代碼中設置項目源。

爲此,您需要將用戶控件的DataContext設置爲您的用戶控件類型。這可以做到無論在後面的代碼爲用戶控件(設置this.DataContext = this),或通過元素在XAML綁定:

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

然而,我的做法是完全不使用的用戶控件,因爲所有你真正討論的是視圖組合,並在其他視圖之間重用視圖的特定部分。

使用MVVM框架(如Caliburn.Micro)來查看構圖非常簡單。在這種情況下,你將有一個AddressViewModelAddressView,並使用ContentControlAddressView注入基本視圖:

<ContentControl x:Name="AddressViewModel" /> 
+0

我同意這是一個非常簡單的。這是我對另外幾個人的概念驗證,我認爲這些複雜的多重嵌套控件更復雜。我對DependencyProperties不熟悉,所以我想確保我使用的是最佳實踐方法,而不是從臀部拍攝,然後後來發現我在腳下開槍自殺。 :) – 2012-02-10 00:02:21