[英]Properly bind DependencyProperty of UserControl in MVVM
[英]How to bind a DependencyProperty of a UserControl to a property in it's ViewModel in MVVM?
問題不在於如何使這些東西正常工作,它已經可以了。 這是關於我正在經歷的一些奇怪行為,我需要了解它。 我有一個包含一些樣式的ResourceDictionary
,其中一種樣式為TargetType="{x:Type UserControl}"
和x:Key="UCStyle"
; 將其應用於項目中的多個UserControl
。 這些UserControl
的其中一些在其ViewModel中具有string State
屬性,可用於應用視覺狀態(通過外部類和附加屬性,綁定到XAML中的ViewModel)。 到現在為止一切都非常完美,然后,我嘗試將DependencyProperty State
添加到UserControl
,然后將其綁定到ViewModel中的state屬性,我的嘗試是:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!--ResourceDictionary Source="..."/-->
</ResourceDictionary.MergedDictionaries>
<Style x:Key="MyStyle" TargetType="{x:Type local:MyUserControl}" BasedOn="{StaticResource UCStyle}">
<Setter Property="State" Value="{Binding State, Mode=TwoWay}"/>
</Style>
</ResourceDictionary>
</UserControl.Resources>
<UserControl.Style>
<DynamicResourceExtension ResourceKey="MyStyle" />
</UserControl.Style>
並顯示錯誤提示:
'MyUserControl'TargetType與元素'UserControl'的類型不匹配。
而且不適既不UCStyle
也不MyStyle
在XAML瀏覽器在Visual Studio中,甚至不畫小孩UserControl
s請正確。 我沒想到解決方案可以正常運行,但是確實可以!
現在我的問題是:
我正在使用Visual Studio 2012。
WPF設計器在設計時顯示偽造的錯誤是有害的。 您不能做很多事,但是請忽略它們。
視覺狀態是UI的關注點,因此應包含在UI中。 MVVM 並不意味着沒有代碼隱藏。 將您的代碼隱藏用於UI任務,並將業務邏輯放入視圖模型中。
您的問題表明您正在創建自定義視圖模型,以保留用戶控件的視圖邏輯。 說真的,不要那樣做。 那會給您帶來麻煩。 它會干擾數據綁定的設計工作方式。
沒有將用戶控制元素綁定到其表面上定義的屬性的“最佳實踐”。 這取決於。 但是,使用樣式執行此操作似乎很奇怪。 您可以簡單地為UserControl的根賦予x:Name="root"
,然后在綁定中使用ElementName=root
。
在UserControl中綁定到UserControl上定義的屬性的示例(取自舊的原型)...
這是一個旨在添加或刪除內容列表的UserControl。
我不保證這項工作有效,但可以說明如何完成:
public partial class ItemsEditor : UserControl
{
#region Items
public static readonly DependencyProperty ItemsProperty =
DependencyProperty.Register(
"Items",
typeof(IEnumerable<Item>),
typeof(ItemsEditor),
new UIPropertyMetadata(null));
public IEnumerable<Item> Items
{
get { return (IEnumerable<Item>)GetValue(ItemsProperty); }
set { SetValue(ItemsProperty, value); }
}
#endregion
#region AddItem
public static readonly DependencyProperty AddItemProperty =
DependencyProperty.Register(
"AddItem",
typeof(ICommand),
typeof(ItemsEditor),
new UIPropertyMetadata(null));
public ICommand AddItem
{
get { return (ICommand)GetValue(AddItemProperty); }
set { SetValue(AddItemProperty, value); }
}
#endregion
#region RemoveItem
public static readonly DependencyProperty RemoveItemProperty =
DependencyProperty.Register(
"RemoveItem",
typeof(ICommand),
typeof(ItemsEditor),
new UIPropertyMetadata(null));
public ICommand RemoveItem
{
get { return (ICommand)GetValue(RemoveItemProperty); }
set { SetValue(RemoveItemProperty, value); }
}
#endregion
public ItemsEditor()
{
InitializeComponent();
}
}
它僅列出了一堆東西,您可以添加新東西或從列表中刪除東西。 這是xaml中的綁定
<UserControl x:Class="LolPrototype.ItemsEditor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:t="clr-namespace:UCsAndICommands"
x:Name="root">
<UserControl.Resources>
<DataTemplate DataType="{x:Type t:Item}">
<StackPanel Orientation="Horizontal">
<Button Command="{Binding RemoveItem, ElementName=root}"
CommandParameter="{Binding}">Remove</Button>
<TextBox Text="{Binding Name}" Width="100"/>
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<StackPanel>
<Button Command="{Binding AddItem, ElementName=root}">Add</Button>
<ItemsControl ItemsSource="{Binding Items, ElementName=root}" />
</StackPanel>
</UserControl>
顯然,您可以在祖先資源的列表之外定義DataTemplates。 關鍵是要顯示如何使用ElementName綁定來綁定UserControl中定義的屬性。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.