您的位置:首页 > 职场人生

二十三:采用用DataTemplate实现CheckListBox的CustomControl

2008-01-15 13:12 501 查看
(感谢Microsoft公司的Ocean Ju提供本文章的思路)。
  创建CustomControl的步骤我就不再累述,不清楚的请参考综合应用WPF/WCF/WF/LINQ之三:采用用代码创建的方式实现CheckListBox的CustomControl

  为了方便大家学习,请单击此处下载该程序的代码。注意:代码中的GetProperty、GetControl等为扩展方法,具体代码请参考源代码。
  这次Themes\CheckListBox.xaml的内容为:
1 <ResourceDictionary
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:local="clr-namespace:Eallies.OA.UI.Controls.Common">
5
6 <local:CheckListBoxItemConverter x:Key="CheckListBoxItemConverter" />
7
8 <Style TargetType="{x:Type local:CheckListBox}" BasedOn="{StaticResource {x:Type ListBox}}">
9 <Setter Property="ItemTemplate">
10 <Setter.Value>
11 <DataTemplate>
12 <CheckBox Name="chkCheckBox">
13 <CheckBox.Tag>
14 <MultiBinding Converter="{StaticResource CheckListBoxItemConverter}">
15 <MultiBinding.Bindings>
16 <Binding />
17 <Binding Path="ItemValuePath" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type local:CheckListBox}}" />
18 </MultiBinding.Bindings>
19 </MultiBinding>
20 </CheckBox.Tag>
21 <CheckBox.Content>
22 <MultiBinding Converter="{StaticResource CheckListBoxItemConverter}">
23 <MultiBinding.Bindings>
24 <Binding />
25 <Binding Path="ItemContentPath" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type local:CheckListBox}}" />
26 </MultiBinding.Bindings>
27 </MultiBinding>
28 </CheckBox.Content>
29 </CheckBox>
30 </DataTemplate>
31 </Setter.Value>
32 </Setter>
33 </Style>
34
35 </ResourceDictionary>
  我们的思路是:具体Binding哪个字段可以用ItemValuePath和ItemContentPath这两个字段来配置,而根据字段名来取值则采用反射的方法。为了实现这个思路,我们需要使用Binding的Converter技术。这里需要传入两个参数,一个是当前Item,一个是字段名,因此我们采用MultiBinding技术。该Converter类的代码如下:
1 public class CheckListBoxItemConverter : IMultiValueConverter
2 {
3 #region IMultiValueConverter Members
4
5 public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
6 {
7 try
8 {
9 object item = values[0];
10 string name = values[1] as string;
11
12 return item.GetProperty(name).GetValue(item, null);
13 }
14 catch
15 {
16 throw;
17 }
18 }
19
20 public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
21 {
22 throw new NotSupportedException("Not supported.");
23 }
24
25 #endregion
26 }
  而这两个字段名,则可以采用DependencyProperty技术来实现:
1 public string ItemValuePath
2 {
3 get { return (string)GetValue(ItemValuePathProperty); }
4 set { SetValue(ItemValuePathProperty, value); }
5 }
6
7 public static readonly DependencyProperty ItemValuePathProperty =
8 DependencyProperty.Register("ItemValuePath", typeof(string), typeof(CheckListBox));
9
10 public string ItemContentPath
11 {
12 get { return (string)GetValue(ItemContentPathProperty); }
13 set { SetValue(ItemContentPathProperty, value); }
14 }
15
16 public static readonly DependencyProperty ItemContentPathProperty =
17 DependencyProperty.Register("ItemContentPath", typeof(string), typeof(CheckListBox));
  至此,我们已经能够实现对CheckListBox控件的数据绑定了。
  但还不够,我们需要处理CheckBox的Checked和Unchecked事件。为了处理这个问题,我们采用EventManager.RegisterClassHandler方法来注册CheckBox的CheckedEvent和UncheckedEvent。这里需要注意的是:如果界面上有两个以上的CheckListBox控件,则两个控件中的OnChecked和OnUnchecked事件都会触发,因此,我们需要做一个判断:if (sender.Equals(this) == false) return;
1 public CheckListBox()
2 {
3 EventManager.RegisterClassHandler(typeof(CheckListBox), CheckBox.CheckedEvent, new RoutedEventHandler(OnChecked));
4 EventManager.RegisterClassHandler(typeof(CheckListBox), CheckBox.UncheckedEvent, new RoutedEventHandler(OnUnchecked));
5 }
6
7 private void OnChecked(object sender, RoutedEventArgs e)
8 {
9 try
10 {
11 if (sender.Equals(this) == false) return;
12
13 this._CheckedValues.Add((e.OriginalSource as CheckBox).Tag.ToType<int>());
14 }
15 catch
16 {
17 throw;
18 }
19 }
20
21 private void OnUnchecked(object sender, RoutedEventArgs e)
22 {
23 try
24 {
25 if (sender.Equals(this) == false) return;
26
27 this._CheckedValues.Remove((e.OriginalSource as CheckBox).Tag.ToType<int>());
28 }
29 catch
30 {
31 throw;
32 }
33 }
  至此,剩下的问题就只有解决为CheckBox控件赋值的问题了。
1 public void SetIsChecked(int index, bool value)
2 {
3 try
4 {
5 (this.GetControl("chkCheckBox", this.ItemValuePath, index) as CheckBox).IsChecked = value;
6 }
7 catch
8 {
9 throw;
10 }
11 }

附件:http://down.51cto.com/data/2350002
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐