[英]How to bind DataTemplate width to parent and be able to update viewmodel property?
[英]WinUI 3 How to Bind Command to ViewModel property when using a DataTemplate?
我正在使用一個名為MainGrid
的Grid
來 position 一個ItemsRepeater
,它的ItemsSource
綁定到我的ViewModel
中的ObservableCollection
。
<muxc:ItemsRepeater
ItemsSource="{Binding Path=Molts}"
Layout="{StaticResource VerticalStackLayout}"
ItemTemplate="{StaticResource MoltTemplate}">
</muxc:ItemsRepeater>
我創建了一個DataTemplate
<DataTemplate x:Key="MoltTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="text" Text="{Binding ID}"></TextBlock>
<Button Command="{Binding DisplayAvailAIsCommand}" CommandParameter="{Binding ElementName=text, Path=Text}">Add</Button>
</StackPanel>
</DataTemplate>
其中有一個TextBox
和Button
。 我希望Button
在我的ViewModel
中觸發命令,但ItemsRepeater
中的項目將其DataContext
設置為Model
class 而不是ViewModel
。 我發現這篇文章指出我可以通過將ElementName
設置為一個 UI 元素來更改我的Button
的Command
以將DataContext
設置為我的ViewModel
,該 UI 元素的DataContext
是ViewModel
<Button Command="{Binding DataContext.DisplayAvailAIsCommand, ElementName=MainGrid}" CommandParameter="{Binding ElementName=text, Path=Text}">Add</Button>
我的 window 的構造函數像這樣設置MainGrid
的DataContext
public MainWindow()
{
this.InitializeComponent();
MainGrid.DataContext = new MoltViewModel();
}
但是,這不起作用,並且命令不會觸發。 我究竟做錯了什么?
您可以通過創建綁定到源屬性的附加屬性來解決此限制:
public abstract class BindingServices : DependencyObject
{
public static readonly DependencyProperty ViewModelCommandProperty = DependencyProperty.RegisterAttached(
"ViewModelCommand",
typeof(string),
typeof(BindingServices),
new PropertyMetadata(null, new PropertyChangedCallback(OnSet))
);
public static void SetViewModelCommand(Button element, string value) =>
element.SetValue(ViewModelCommandProperty, value);
public static string GetViewModelCommand(Button element) =>
(string)element.GetValue(ViewModelCommandProperty);
private static void OnSet(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Button button = (Button)d;
button.Loaded += OnButtonLoaded;
}
private static void OnButtonLoaded(object sender, RoutedEventArgs e)
{
Button button = (Button)sender;
button.Loaded -= OnButtonLoaded;
button.SetBinding(ButtonBase.CommandProperty, new Binding()
{
Path = new PropertyPath(GetViewModelCommand(button)),
Source = FindParent<ItemsRepeater>(button)?.DataContext
});
}
private static T FindParent<T>(DependencyObject dependencyObject) where T : DependencyObject
{
DependencyObject parent = VisualTreeHelper.GetParent(dependencyObject);
if (parent == null)
return null;
return (parent as T) ?? FindParent<T>(parent);
}
}
上述實現查找父ItemsRepeater
的DataContext
的屬性。
示例用法:
<Button ... local:BindingServices.ViewModelCommand="DisplayAvailAIsCommand" />
或者,您可以處理Click
事件並從視圖的代碼隱藏 class 調用命令:
private void Button_Click(object sender, RoutedEventArgs e) =>
(MainGrid.DataContext as MoltViewModel)?.DisplayAvailAIsCommand?.Execute(null);
XAML:
<Button ... Click="Button_Click" />
這不會破壞 MVVM 模式,因為您從與使用{Binding DisplayAvailAIsCommand}
XAML 標記連接命令時相同的視圖調用相同的視圖 model 命令。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.