WPF Caliburn Micro Message.Attach 没有通过 HierarchicalDataTemplate 冒泡
WPF Caliburn Micro Message.Attach not bubbling up through HierarchicalDataTemplate
我正在尝试在 TreeView
中连接删除按钮,以便它在其直接父视图模型中调用 Remove
方法。
我收到此异常:System.Exception: 'No target found for method Remove.'
当我单击“删除”按钮时。
如果我将 Remove
方法从 B_ViewModel
移动到 SomeViewModel
,它会被调用,但我不想那样实现它。
如何告诉 Message.Attach
冒泡到其直接父级?
这里是 SomeView.xaml
:
<TreeView ItemsSource="{Binding As}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type vm:A_ViewModel}"
ItemsSource="{Binding Bs}">
<TextBlock Text="{Binding AName}" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type vm:B_ViewModel}"
ItemsSource="{Binding Cs}">
<TextBlock Text="{Binding BName}" />
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type vm:C_ViewModel}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding CName}" />
<Button Margin="2"
cal:Message.Attach="Remove($dataContext)"
Content="Delete"/>
</StackPanel>
</DataTemplate>
</TreeView.Resources>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="True" />
</Style>
</TreeView.ItemContainerStyle>
这是我的视图模型:
public class SomeViewModel: Screen
{
public BindableCollection<A_ViewModel> As { get; private set; }
= new BindableCollection<A_ViewModel>();
public SomeViewModel()
{
var a = new A_ViewModel() { AName = "A1" };
var b = new B_ViewModel() { BName = "B1" };
b.Cs.Add(new C_ViewModel() { CName = "C1" });
b.Cs.Add(new C_ViewModel() { CName = "C2" });
a.Bs.Add(b);
this.As.Add(a);
}
}
public class A_ViewModel: PropertyChangedBase
{
public BindableCollection<B_ViewModel> Bs { get; private set; }
= new BindableCollection<B_ViewModel>();
public A_ViewModel()
{
}
private string _aName;
public string AName
{
get { return _aName; }
set { Set(ref _aName, value); }
}
}
public class B_ViewModel : PropertyChangedBase
{
public BindableCollection<C_ViewModel> Cs { get; private set; }
= new BindableCollection<C_ViewModel>();
private string _bName;
public string BName
{
get { return _bName; }
set { Set(ref _bName, value); }
}
public void Remove(C_ViewModel c)
{
if (this.Cs.Contains(c))
this.Cs.Remove(c);
else
Debug.Print(c.CName + " not found");
}
}
public class C_ViewModel : PropertyChangedBase
{
private string _cName;
public string CName
{
get { return _cName; }
set { Set(ref _cName, value); }
}
}
您可以使用附加的 cal:Action.TargetWithoutContext
属性 将 Button
的 DataContext
设置为父级 B_ViewModel
:
<DataTemplate DataType="{x:Type vm:C_ViewModel}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding CName}" />
<Button Margin="2"
cal:Action.TargetWithoutContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType=TreeViewItem, AncestorLevel=2}}"
cal:Message.Attach="Remove($dataContext)"
Content="Delete"/>
</StackPanel>
</DataTemplate>
我正在尝试在 TreeView
中连接删除按钮,以便它在其直接父视图模型中调用 Remove
方法。
我收到此异常:System.Exception: 'No target found for method Remove.'
当我单击“删除”按钮时。
如果我将 Remove
方法从 B_ViewModel
移动到 SomeViewModel
,它会被调用,但我不想那样实现它。
如何告诉 Message.Attach
冒泡到其直接父级?
这里是 SomeView.xaml
:
<TreeView ItemsSource="{Binding As}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type vm:A_ViewModel}"
ItemsSource="{Binding Bs}">
<TextBlock Text="{Binding AName}" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type vm:B_ViewModel}"
ItemsSource="{Binding Cs}">
<TextBlock Text="{Binding BName}" />
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type vm:C_ViewModel}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding CName}" />
<Button Margin="2"
cal:Message.Attach="Remove($dataContext)"
Content="Delete"/>
</StackPanel>
</DataTemplate>
</TreeView.Resources>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="True" />
</Style>
</TreeView.ItemContainerStyle>
这是我的视图模型:
public class SomeViewModel: Screen
{
public BindableCollection<A_ViewModel> As { get; private set; }
= new BindableCollection<A_ViewModel>();
public SomeViewModel()
{
var a = new A_ViewModel() { AName = "A1" };
var b = new B_ViewModel() { BName = "B1" };
b.Cs.Add(new C_ViewModel() { CName = "C1" });
b.Cs.Add(new C_ViewModel() { CName = "C2" });
a.Bs.Add(b);
this.As.Add(a);
}
}
public class A_ViewModel: PropertyChangedBase
{
public BindableCollection<B_ViewModel> Bs { get; private set; }
= new BindableCollection<B_ViewModel>();
public A_ViewModel()
{
}
private string _aName;
public string AName
{
get { return _aName; }
set { Set(ref _aName, value); }
}
}
public class B_ViewModel : PropertyChangedBase
{
public BindableCollection<C_ViewModel> Cs { get; private set; }
= new BindableCollection<C_ViewModel>();
private string _bName;
public string BName
{
get { return _bName; }
set { Set(ref _bName, value); }
}
public void Remove(C_ViewModel c)
{
if (this.Cs.Contains(c))
this.Cs.Remove(c);
else
Debug.Print(c.CName + " not found");
}
}
public class C_ViewModel : PropertyChangedBase
{
private string _cName;
public string CName
{
get { return _cName; }
set { Set(ref _cName, value); }
}
}
您可以使用附加的 cal:Action.TargetWithoutContext
属性 将 Button
的 DataContext
设置为父级 B_ViewModel
:
<DataTemplate DataType="{x:Type vm:C_ViewModel}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding CName}" />
<Button Margin="2"
cal:Action.TargetWithoutContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType=TreeViewItem, AncestorLevel=2}}"
cal:Message.Attach="Remove($dataContext)"
Content="Delete"/>
</StackPanel>
</DataTemplate>