0

いくつかのコントロールを備えたウィンドウがあり、それらは必然的に相互にviewModelsを参照します。関連するコントロールのグループをカスタムUserControlに移動したいのですが、移動すると、ウィンドウ内の他のコントロールから現在埋め込まれているコントロールへのバインドに問題があります。

たとえば、私のウィンドウにはグリッドがあります。グリッドの1つのセルに、2つのカスタムUserControlを含むStackPanelがあります。

<StackPanel>
    <KtWpf:TicketGridControl x:Name="ticketGrid" />
    <KtWpf:TicketViewControl x:Name="ticketView" />
</StackPanel>

グリッドの別のセルに、グリッド内の現在のアイテムにバインドする別のカスタムUserControlがあります。

<local:AddressView x:Name="addressView"
    currentItem="{Binding ElementName=ticketGrid,Path=viewModel.tickets.CurrentItem}" />

そして、そのバインディングは正常に機能します。

しかし、私が欲しいのは、ticketGridとticketViewを新しいカスタムUserControlに移動することです。これは簡単に実行できます。

<UserControl
        x:Class="KorEnterprise.EnterpriseMobile.MyTickets"
        ...
        >
    <StackPanel>
        <KtWpf:TicketGridControl x:Name="ticketGrid" />
        <KtWpf:TicketViewControl x:Name="ticketViewControl" />
    </StackPanel>
</UserControl>

次に、グリッドで、StackPanelを次のように置き換えます。

<local:MyTickets x:Name="myTickets" />

そして、addressViewのバインディングが次のように変更されることを期待します。

<local:AddressView x:Name="addressView"
    currentItem="{Binding ElementName=myTickets,Path=ticketGrid.viewModel.tickets.CurrentItem}" />

しかし、これは機能しません。実行時にBindingExpressionエラーが発生します。

System.Windows.Data Error: 40 : 
BindingExpression path error: 'ticketGrid' property not found on 'object' ''MyTickets' (Name='myTickets')'. 
BindingExpression:Path=ticketGrid.viewModel.tickets.CurrentItem; 
DataItem='MyTickets' (Name='myTickets'); 
target element is 'AddressView' (Name='addressView'); 
target property is 'currentItem' (type 'TicketVM')

そして、その理由がわかりません。コンパイル時にエラーは発生しません。コードにエラーは発生しません。

たとえば、これは例外をスローしません。

public MainWindow()
{
    ...
    this.applicationExiting += new ApplicationExitingEventHandler(this.myTickets.ticketGrid.applicationExitingEventHandler);
    ...
}

デバッガーをウォークスルーすると、this.myTicketsが存在し、this.myTickets.ticketGridが存在し、イベントハンドラーが正常に接続されます。

しかし、XAMLがサイレントマジックを開始し、バインディングをフックすると、何らかの理由でthis.myTickets.ticketGridが存在しなくなります。

そして、私はその理由を理解するのに途方に暮れています。

4

2 に答える 2

0

これが最善のアプローチかどうかはまったくわかりませんが、機能します。それは私が望んでいたよりも多くの配管を必要とします。

  • ビューモデルクラスを作成し、そのインスタンスをコントロールのDataContextに設定します。
  • ビューモデルにチケットコレクションプロパティを作成します
  • ユーザーコントロールが構築されたら、ビューモデルのチケットコレクションをticketGridのチケットコレクションに設定します
  • AddressViewコントロールのcurrentItemプロパティをビューモデルのチケットコレクションにバインドします
  • そして最も重要なのは、ビューモデルのチケットコレクションが変更されたときにPropertyChangedを発生させることです。

これは機能しますが、もっと簡単なものを見つけたいと思います。

public partial class MyTickets : KorUserControl
{
    public MyTickets()
    {
        InitializeComponent();

        this.DataContext = new MyTicketsVM();
        this.viewModel.tickets = this.ticketGrid.viewModel.tickets;
    }

    public MyTicketsVM viewModel
    {
        get { return this.DataContext as MyTicketsVM; }
    }
}

public class MyTicketsVM : MyViewModelBase
{
    private QueryableCollectionView _tickets;
    public QueryableCollectionView tickets
    {
        get { return this._tickets; }
        internal set
        {
            this._tickets = value;
            notifyPropertyChanged("tickets");
        }
    }
}

<local:AddressView
    x:Name="addressView"
    currentItem="{Binding ElementName=myTickets,Path=viewModel.tickets.CurrentItem}"
    />

(注:MyViewModelBaseはINotifyPropertyChangedを実装します)

于 2012-10-15T19:26:16.767 に答える
0

試す :

 <local:MyTickets x:Name="myTickets" 
        Tag="{Binding ElementName=ticketGrid,Path=YourProperty}" /> 

と:

  <local:AddressView currentItem="{Binding ElementName=myTickets,Path=Tag}" />

わかりました、これは機能しません..

以下をせよ :

UserControlにDependencyPropertyを作成します。

  public Class MyTickets: UserControl 
  {
       public object MyProperty
       {
           get { return (object)GetValue(MyPropertyProperty); }
           set { SetValue(MyPropertyroperty, value); }
       }

       public static readonly DependencyProperty MyPropertyProperty=
        DependencyProperty.Register("MyProperty", typeof(object), typeof(MyTickets), new UIPropertyMetadata(null));

  }

XAML:

 <UserControl
    x:Class="KorEnterprise.EnterpriseMobile.MyTickets"
    ...
    >
          <StackPanel>
              <KtWpf:TicketGridControl x:Name="ticketGrid" 
                                YourProperty={Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl} , 
                                Path=MyProperty />
              <KtWpf:TicketViewControl x:Name="ticketViewControl" />
          </StackPanel>

と :

 <local:AddressView currentItem="{Binding ElementName=myTickets,Path=MyProperty }" />
于 2012-10-15T18:09:25.073 に答える