2016-07-07 9 views
1

MVVM WPFパターンに関する依存関係プロパティを持つカスタムコントロールを作成できますか?MVVM WPFアーキテクチャでカスタムUserControlを作成する方法

はいの場合、別のMVVMアプリケーションでCustomControlをどのように使用して、依存関係のプロパティを公開しますか?

EDIT:私は「TestCustomControl」という名前の別のWPFアプリケーションでそれを使用し、その後customControlを作成することを可能にする簡単な例以下

しかし、依存関係のプロパティは私のために全く機能しません。

enter image description here

CustomControlView.xaml

<UserControl xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid" xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors" x:Class="MyCustomControl.MyCustomUserControl" 
     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" 
     xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm" 
     xmlns:myCustomControl="clr-namespace:MyCustomControl" 
     mc:Ignorable="d" 
     d:DesignHeight="300" d:DesignWidth="300"> 

<dxmvvm:Interaction.Triggers> 
    <dxmvvm:EventToCommand Command="{Binding LoadCommand}" EventName="Loaded" /> 
</dxmvvm:Interaction.Triggers> 

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="*" /> 
    </Grid.RowDefinitions> 

    <dxe:ButtonEdit Height="40" Grid.Row="0"/> 
    <dxg:GridControl Grid.Row="1" ItemsSource="{Binding MyItems}" AutoGenerateColumns="AddNew"/> 
</Grid> 

CustomControlView.xaml.cs

using System.Windows; 
using System.Windows.Controls; 
namespace MyCustomControl 
{ 
    /// <summary> 
    /// Interaction logic for MyCustomUserControl.xaml 
    /// </summary> 
    public partial class MyCustomUserControl : UserControl 
    { 
     public MyCustomUserControl() 
     { 
      InitializeComponent(); 
      this.DataContext = new CustomControlViewModel(FilePath); 
     } 
     /// <summary> 
     /// File Path 
     /// </summary> 
     public static readonly DependencyProperty FilePathProperty = DependencyProperty.Register(
      "FilePath", typeof(string), typeof(MyCustomUserControl), new PropertyMetadata(string.Empty)); 
     public string FilePath 
     { 
      get { return (string)GetValue(FilePathProperty); } 
      set 
      { 
       SetValue(FilePathProperty, value); 
      } 
     } 
    } 
} 

CustomControlViewModel.cs

using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.IO; 
using System.Linq; 
using DevExpress.Mvvm; 
using DevExpress.Mvvm.DataAnnotations; 
namespace MyCustomControl 
{ 
    public class CustomControlViewModel:ViewModelBase 
    { 
     #region Fields 
     private ObservableCollection<string> _myItems; 
     private string _path; 
     #endregion 

     #region Constructors 
     public CustomControlViewModel(string path) 
     { 
      _path = path; 
     } 
     #endregion 

     #region Commands 

     [Command] 
     public void Load() 
     { 
      IEnumerable<string> allLinesText = new List<string>(); 
      try 
      { 
       allLinesText = File.ReadAllLines(_path).ToList(); 
      } 
      catch (Exception e) 
      { 

       Console.WriteLine(e.ToString()); 
      } 

      MyItems = new ObservableCollection<string>(allLinesText); 
     } 
     #endregion 

     #region Properties 
     public ObservableCollection<string> MyItems 
     { 
      get { return _myItems; } 
      set { SetProperty(ref _myItems, value,() => MyItems); } 
     } 
     #endregion 
    } 
} 

MainWindow.xaml

<Window xmlns:MyCustomControl="clr-namespace:MyCustomControl;assembly=MyCustomControl" 
    x:Class="TestCustomControl.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:testCustomControl="clr-namespace:TestCustomControl" 
    Title="MainWindow" Height="350" Width="525"> 
<Window.DataContext> 
    <testCustomControl:MainViewModel/> 
</Window.DataContext> 
<Grid> 
    <MyCustomControl:MyCustomUserControl FilePath="{Binding MyFile}"/> 
</Grid> 

MainViewModel.cs

using DevExpress.Mvvm; 
namespace TestCustomControl 
{ 
    public class MainViewModel: ViewModelBase 
    { 
     #region Fields 
     private string _myFile;   
     #endregion 

     #region Constructors 
     public MainViewModel() 
     { 
      MyFile = "List.txt"; 
     } 
     #endregion 

     #region Properties 
     public string MyFile 
     { 
      get { return _myFile; } 
      set { SetProperty(ref _myFile, value,() => MyFile); } 
     } 
     #endregion 
    } 
} 

NB: "list.txtには"「.. \に置かれたファイルですTestCustomControl \ bin \ Debug "

誰かが私の依存関係プロパティが機能しない理由を見つけるのを手助けできますか?

+0

UserControlまたはカスタムコントロールは、データバインディングをサポートするために、常に依存プロパティを公開します。ただし、これはアプリケーションのアーキテクチャとはまったく関係ありません。 MVVMかどうかは、UserControlコードには関係ありません。注意すべきことは、典型的なUserControlは独自のビューモデルを定義すべきではないことです。特に、独自のDataContextを明示的に設定するべきではありません。代わりに、親コントロールまたはウィンドウからDataContextを継承する必要があります。 – Clemens

+1

再利用可能なコントロールは、UIのみであり、独自のビューモデルを持つべきではありません。 TextBoxにTextBoxViewModelがない様に。 DependencyPropertiesとして必要なものだけを公開し、コードをコードビハインドに置き、任意のタイプのWPFアプリケーションでそのコントロールを使用できます。 – Will

+0

@Willこれは '文字列'にしか束縛されない 'Textbox'のような単純なものの良いアドバイスのようです。しかし、複雑なやネストされたプロパティを持つ 'User'クラスのような複雑なものを編集するためのユーザコントロールはどうでしょうか?確かに 'User'のユーザコントロールは' User'のインスタンスにバインドされます。 'User'はコントロールのView Modelと見なされませんか?いくつかの点で、 'string'は' Textbox'のためのView Modelです。 –

答えて

0

これは明らかに可能であり、カスタムコントロールを作成するための最良の方法です。依存プロパティなしでは、カスタムコントロールを簡単に再利用することができないためです。再利用性は、依存性のプロパティによって非常に簡単になります。依存関係のプロパティとしてICommandをイベントとして使用すると、MVVMパターンに従い、より洗練されたコードを背後に置くことができます。

別のMVVMアプリケーションでCustomControlを再利用する方法を詳しく説明すると、ここでは答えが広すぎます。あなたはVisual Studioに行きカスタムコントロールを作成することができます。コードの背後には、ビュー内でダイナミックであると考えるプロパティにバインドされたいくつかの依存プロパティが定義されています。この非常にcustomcontrolを別のアプリケーションで再利用し、再利用中にこれらのプロパティを設定します。

また、一部のイベントをビューモデルにルーティングするためにICommandを試すこともできます。すなわち、リストアイテム選択変更イベントに対する依存性プロパティは、対応するビューモデルにコマンドをルーティングすることができる。

+0

私はカスタムコントロールを作成することが可能であることを知っています。しかし、問題はMVVMアーチでそれを作成することです。私はすでに依存関係プロパティを持つカスタムコントロールをコードの背後に作成したので、別のwpfアプリケーションでもそれを消費しました。しかし、MVVMでカスタムコントロールを作成しようとしたとき、依存プロパティを消費しませんでした!!! – xtensa1408

+0

誰がMVVMの依存プロパティを消費できないと言ったのですか?明らかに可能です。ボタンから派生したカスタムコントロールがあるとします。 MVVMを使用したいとします。 ** ICommand ** say ** ButtonDoubleClicked **型のコードの依存関係プロパティを定義します。ボタンのダブルクリックハンドラでこのコマンドを実行します。このカスタムコントロールを再利用するときは、対応するビューモデルのICommandプロパティに** ButtonDoubleClicked **を定義すれば呼び出されます。これはほんの一例です。あなたはGoogleでたくさんの例を得ることができます。 – ViVi

+0

@ xtensa1408:再利用可能なコントロールはビューモデルを持たず、ビューモデルを必要としません。あなただけのコードでカスタムコントロールを作成することができます。その後、ビューモデルにバインドされたビューで再利用することができます。あなたはポイントを得ることを願っています。 – ViVi

関連する問題