2012-02-28 15 views
2

私はTelerik RadGridViewとTelerik DataFormを含む2つの異なるUserControlを持つフォームを持っています。UserControlのDependencyPropertyへのバインド

グリッドusercontrolは、グリッドがバインドされているItemsコレクションを公開するプロパティを含むViewModelにバインドされています。

フォームをそのプロパティにバインドすると、すべて正常に動作します。
しかし、実際にグリッドコントロールのviewmodelに属していないフォームコントロールの追加情報にアクセスする必要があります。

だから私は、私は、フォームのユーザーコントロールにプロパティを追加し、アイテムコレクションにバインドしようと思いました。フォームのコードビハインドで

<local:FormControl x:Name="formControl" 
    ItemsSource="{Binding items}" 
/> 

、私は通常のプロパティを追加しました:

private object itemsSource; 
public object ItemsSource 
{ 
    get { return this.itemsSource; } 
    set { this.itemsSource = value; } 
} 

これはもちろん動作しませんでした。 DependencyPropertyを使用する必要があるというエラーが表示されます。私は安心していたと思っていました。ページは実際に私が考えるべき財産に縛り付けようとしていました。

だから私はしたDependencyPropertyにこれを変換:

public static DependencyProperty ItemsSourceProperty = 
    DependencyProperty.Register("ItemsSource", typeof(object), typeof(FormControl)); 

public object ItemsSource 
{ 
    get { return GetValue(ItemsSourceProperty); } 
    set { SetValue(ItemsSourceProperty, value); } 
} 

コンパイルエラーなしで実行されたこと。もちろん、コントロールのビューモデルにはアイテムがありませんでした。次に、フォームコントロールのビューモデルにItemsSourceプロパティを渡そうとしました。

public FormControl() 
{ 
    InitializeComponent(); 
    this.DataContext = new FormControlVM(this.ItemsSource); 
    ... 

これは機能しませんでした。 FormControl()が構築されたとき、ItemsSourceはnullでした。そこで、viewModelにsetItemsSource()メソッドを追加し、それをItemsSourceプロパティのset関数で呼び出しました。これもうまくいかなかった。 xamlは明らかにプロパティにバインドされていますが、プロパティのset関数を呼び出さずにそのように見えます。

だから私はしたDependencyPropertyに、ValueChangedイベントに耳を傾けることにしました:

public FormControl() 
{ 
    InitializeComponent(); 
    this.DataContext = new FormControlVM(); 
    DependencyPropertyDescriptor prop = 
      DependencyPropertyDescriptor.FromProperty(FormControl.ItemsSourceProperty, this.GetType()); 
    prop.AddValueChanged(this, delegate 
    { 
     FormControlVM formControlVM = (FormControlVM)this.DataContext; 
     formControlVM.setItemsSource(this.ItemsSource); 
    }); 
    ... 

そして、それはまだ動作していません。 ValueChangedデリゲートが呼び出されることはありません。

これは簡単なことだと思われますが、私は例をオンラインで見つけることができませんでした。私が考えうるすべての組み合わせを試しました。

どのように私はこれを処理する必要がありますか?結合============

ウィル上

============追加情報は、結合を行うXAMLについての情報を求めていました。

私は、ページののviewmodelにユーザーコントロールをバインド、ユーザーコントロールが含まれているページでこれを置く場合:にユーザーコントロールでフォームを結合、ユーザーコントロールに

<local:FormControl x:Name="formControl" 
     Grid.Column="2" 
     DataContext="{Binding}" 
     /> 

をしてから、このページのビューモデルのitemsCollection:

<telerik:RadDataForm 
     ItemsSource="{Binding itemsCollection}" 
     Header="View Item:" 
     CommandButtonsVisibility="None" 
     AutoGenerateFields="False" 
     /> 

すべて正常に動作します。

しかし問題は、ユーザーコントロールをページのビューモデルにバインドできないことです。私は、ユーザーコントロールのviewmodelに、ページのviewmodelが見てはならない情報を公開する必要があります。

私は、ユーザーコントロール内のフォームをページのビューモデルのプロパティにバインドして、ユーザーコントロールの外部に届かせることはできません。これはカプセル化違反です。これにより、別のページでユーザーコントロールを使用するのがはるかに複雑になり、今後コントロールの内部をどのように変更するかが厳しく制限されます。 (ページは、ユーザーコントロール内のコントロールについて何も知らないはずですが、ユーザーコントロール内のコントロールはそのページについて何も知ってはいけません)。

ページにユーザーコントロールを含めると、コントロールをページのviewmodelのプロパティに設定し、ユーザーコントロール内のコントロールをユーザーコントロールまたはユーザーコントロールのビューモデルのプロパティにバインドする必要があります。

これはかなり一般的な出来事だと思います。しかし、私はどのようにそれが行われるかもしれないかの例を見つけることができませんでした。

+1

Yeesh。あなたがウサギの穴の底にどのようになっているのかを知っていいのですが、なぜあなたがそれを落としたのか分かりません。ItemsControl *にItemsSourceプロパティを追加する必要があり、UserControl内でそのオブジェクトを使って何をしようとしていますか? – Will

+0

FormControlにはFormが含まれ、そのFormにはItemsSourceプロパティがあります。そのプロパティをプロモートしたいので、FormControlをページにドロップすると、FormControlのプロパティにバインドされます。 (Demeterの法則)。 –

+0

あなたは物事を結びつけようとしていますが、バインディングは機能しません。しかし、あなたが働くと思われるバインディングがないxamlをすべて追加したので誰も言わないと思います。 – Will

答えて

3

問題を再現するには:私は、埋め込まれたTelerik DataFormコントロールを含むUserControlを持っています。埋め込みデータフォームのItemsSourceプロパティを、UserControlが配置されているページのDataContextのプロパティにバインドする必要があります。

UserControlにDataContextが設定されていないと、DataContextが継承され、埋め込まれたDataFormのItemsSourceプロパティをそのプロパティに簡単にバインドできますが、UserControlには独自のDataContextがあります。

UserControlがこのページでのみ使用されるように記述されている場合、RelativeSourceバインディングを使用して、埋め込まれたDataFormのItemsSourceプロパティをページのプロパティにバインドできます。しかし、このUserControlは、いくつかの場所で使用することを目的としており、UserControl以外のプロパティにサイレント依存関係を持つことはできません。依存関係を明示的にする必要があります。

UserControlでDependencyPropertyを作成するのが適切ですが、UserControlのviewmodelでプロパティを複製する必要はありません。私がする必要がどのような

1にある:ユーザーコントロールにしたDependencyPropertyを追加します。

public QueryableCollectionView ItemsSource 
{ 
    get { return (QueryableCollectionView)GetValue(ItemsSourceProperty); } 
    set { SetValue(ItemsSourceProperty, value); } 
} 
public static readonly DependencyProperty ItemsSourceProperty = 
    DependencyProperty.Register("ItemsSource", typeof(QueryableCollectionView), typeof(FormControl)); 

注:私は、コールバック関数を実装する必要はありません。

2:

<UserControl 
     ...> 
    <telerik:RadDataForm 
     ItemsSource="{Binding Path=ItemsSource, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" 
     /> 
</UserControl> 

3:バインディングRelativeSourceを使用して、ユーザーコントロールのこの新しいDependencyPropertyに埋め込まれたデータフォームのItemsPropertyをバインド(DataContextのは、オブジェクト型を持つ)適切なタイプで、ページのビューモデルを可視ください:

public partial class MainWindow : Window 
{ 
    public MainWIndow() 
    { 
     this.InitializeComponent(); 
     this.DataContext = new MainWindowVM(); 
    } 
    public MainWindowVM viewModel 
    { get { return this.DataContext as MainWindowVM; } } 
} 

4:

を:ページで、再結合RelativeSourceを使用して、ページののviewmodelの適​​切なプロパティにユーザーコントロールの新しいItemsPropertyたDependencyPropertyのバインド
<Window 
     ...> 
    <local:FormControl 
     ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type telerik:RadPane}},Path=viewModel.items}" 
     /> 
</Window> 
+0

+1のRelativeSource = {RelativeSource AncestorType = {x:タイプUserControl}} –

関連する問題