我有一个带有许多控件的窗口,它们必须引用彼此的viewModels。我想将一组相关控件移动到自定义UserControl中,当我这样做时,我遇到了从窗口中其他控件绑定到现在嵌入控件的问题。
E.g。在我的窗口中,我有一个网格。在Grid的一个单元格中,我有StackPanel包含两个自定义UserControls:
<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>
然后在Grid中,我将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不存在。
我无法理解为什么。
答案 0 :(得分:0)
尝试:
<local:MyTickets x:Name="myTickets"
Tag="{Binding ElementName=ticketGrid,Path=YourProperty}" />
和
<local:AddressView currentItem="{Binding ElementName=myTickets,Path=Tag}" />
o'k所以这不起作用..
执行以下操作:
在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 }" />
答案 1 :(得分:0)
我不确定这是最好的方法,但确实有效。它只涉及比我想要的更多的管道。
这很有效,但我很想找到更简单的东西:
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)