wpf中UserControl的幾種綁定方式


我們經常會抽取一些可重用的控件,某個屬性是否需要重用,直接決定了這個屬性的綁定方式。

1、完全不可重用的控件

有一些與業務強相關的控件,它們的屬性完全來自ViewModel,越是相對復雜的控件,越容易這樣。比如:

// ChooseUc.xaml
<UserControl>
	<StackPanel Orientation="Horizontal">
		<Label Content="選擇一個水果: "/>
		<ComboBox ItemsSource="{Binding Fruits}"/>
	</StackPanel>
</UserControl>

使用的時候直接 <my:ChooseUc /> 即可直接綁定到ViewModel里的 List<Fruit> Fruits ,不用做額外的工作。好處是特別方便,代價是與vm完全耦合。

2、完全可重用的控件

類似的控件多了,就能抽出一些完全可重用的控件,這些控件與業務無關。為了實現這種重用性,要做到:

  1. 抽出所有可變的屬性,定義在控件內部
  2. 綁定控件內定義的這些屬性
  3. 外部使用時,再將這些屬性與vm綁定

具體如下:

// ChooseUc.xaml
<UserControl>
	<StackPanel x:Name="root" Orientation="Horizontal">
		<Label Content="{Binding Header}"/>
		<ComboBox ItemsSource="{Binding Items}"/>
	</StackPanel>
</UserControl>

相應的cs代碼為:

// ChooseUc.xaml.cs
public ChooseUc() {
	InitializeComponent();
	root.DataContext = this; // 這句很關鍵!
}

public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof(IEnumerable), typeof(ChooseUc));
public IEnumerable Items {
	get { return (IEnumerable)GetValue(ItemsProperty); }
	set { SetValue(ItemsProperty, value); }
}

//HeaderProperty類似,此處省略

使用的時候為:

<my:ChooseUc Header="{Binding FruitHeader}" Items="{Binding Fruits}" />

特別注意 root.DataContext = this;這一句把內部的控件與外界隔離了,內部事實上已經看不到ViewModel了,只能看到內部定義的屬性(Header、Items之類的)。麻煩一些,但好處是可以適用於1個標簽+1個下拉框的任何場景,復用性高。

缺點是,在級聯的自定義控件里,簡直是個噩夢。設想有3個UserControl:C>B>A (C包含B、B包含A)。只有C有對應的vm,這種情況下B要包含A的所有屬性。實際情況是,B要包含所有子控件的所有屬性,這無疑是讓人郁悶的!

好在多數情況下我們並不需要級聯嵌套自定義控件,而且我們也可以放棄一些復用性,以獲得默認綁定vm的便利。

3、部分可重用的控件

還有一類情況就是控件部分可重用,考慮這樣一個場景:用戶可以選擇2個水果,這時Fruits可以直接綁到vm里,但SelectedFruit需要分別綁定:

// ChooseUc.xaml
<UserControl x:Name="uc">
	<StackPanel Orientation="Horizontal">
		<Label Content="選擇一個水果: "/>
		<ComboBox ItemsSource="{Binding Fruits}" SelectedItem="{Binding SelectedFruit, ElementName=uc}"/>
	</StackPanel>
</UserControl>

// 類似的,ChooseUc.xaml.cs里定義SelectedFruit依賴屬性

使用的時候為:

<StackPanel>
	<my:ChooseUc SelectedFruit="{Binding Fruit1}" />
	<my:ChooseUc SelectedFruit="{Binding Fruit2}" />
</StackPanel>

這種情況下,即使是級聯,Fruits也不需要重復定義,又獲得了SelectedFruit的靈活性。這里的關鍵是:只把需要復用的屬性,綁定到控件內部,其他屬性繼承vm就好

4、小結

實際開發的過程中,大部分的情況是1+3,即完全不重用+部分重用的控件。即使遇到完全重用的控件,也不大會形成級聯。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM