0

我有一个带有许多控件的窗口,它们必须相互引用彼此的视图模型。我想将一组相关控件移动到自定义 UserControl 中,当我这样做时,我在从窗口中的其他控件绑定到现在嵌入的控件时遇到问题。

例如,在我的窗口中,我有一个网格。在网格的一个单元格中,我有 StackPanel 包含两个自定义用户控件:

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

在 Grid 的另一个单元格中,我有另一个自定义 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 回答