可分组的选择框控件(MVVM下)(Toggle样式 仿造单选框RadioButton,复选框CheckBox功能)
原地址: http://www.cnblogs.com/yk250/p/5660340.html
效果图如下:支持分组的单选框,复选框样式和MVVM下功能的实现。这是项目中一个快捷键功能的扩展。
1,准备工作:VS2015 (15对WPF的支持变得异常的好,调试模式下允许自动更改属性。),随VS发布的Blend,几个基础类:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class RelayCommand : ICommand 2 { 3 #region Fields 4 5 readonly Action<object> _executeAct; 6 readonly Predicate<object> _canExecutePre; 7 private readonly Action _execute; 8 9 private readonly Func<bool> _canExecute; 10 #endregion 11 12 #region Constructors 13 14 /// <summary> 15 /// Creates a new command that can always execute. 16 /// </summary> 17 /// <param name="execute">The execution logic.</param> 18 public RelayCommand(Action<object> execute) 19 : this(execute, null) 20 { 21 } 22 23 /// <summary> 24 /// Creates a new command. 25 /// </summary> 26 /// <param name="execute">The execution logic.</param> 27 /// <param name="canExecute">The execution status logic.</param> 28 public RelayCommand(Action<object> execute, Predicate<object> canExecute) 29 { 30 if (execute == null) 31 { 32 throw new ArgumentNullException("execute"); 33 } 34 35 _executeAct = execute; 36 _canExecutePre = canExecute; 37 } 38 39 40 /// <summary> 41 /// Initializes a new instance of the RelayCommand class that 42 /// can always execute. 43 /// </summary> 44 /// <param name="execute">The execution logic.</param> 45 /// <exception cref="ArgumentNullException">If the execute argument is null.</exception> 46 public RelayCommand(Action execute) 47 : this(execute, null) 48 { 49 } 50 51 /// <summary> 52 /// Initializes a new instance of the RelayCommand class. 53 /// </summary> 54 /// <param name="execute">The execution logic.</param> 55 /// <param name="canExecute">The execution status logic.</param> 56 /// <exception cref="ArgumentNullException">If the execute argument is null.</exception> 57 public RelayCommand(Action execute, Func<bool> canExecute) 58 { 59 if (execute == null) 60 { 61 throw new ArgumentNullException("execute"); 62 } 63 64 _execute = execute; 65 _canExecute = canExecute; 66 } 67 68 #endregion 69 70 #region ICommand Members 71 72 public bool CanExecute(object parameter) 73 { 74 if (parameter == null) 75 { 76 return _canExecute == null ? true : _canExecute(); 77 } 78 79 return _canExecutePre == null ? true : _canExecutePre(parameter); 80 } 81 82 public event EventHandler CanExecuteChanged 83 { 84 add { CommandManager.RequerySuggested += value; } 85 remove { CommandManager.RequerySuggested -= value; } 86 } 87 88 public void Execute(object parameter) 89 { 90 if (!CanExecute(parameter)) 91 return; 92 if (parameter == null) 93 { 94 if (_execute != null) 95 _execute(); 96 return; 97 } 98 if (_executeAct != null) 99 _executeAct(parameter); 100 101 } 102 103 #endregion 104 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class ModelBase : INotifyPropertyChanged 2 { 3 /// <summary> 4 /// 属性改变事件 5 /// </summary> 6 public event PropertyChangedEventHandler PropertyChanged; 7 8 /// <summary> 9 /// 触发属性改变 10 /// </summary> 11 /// <param name="propertyName"></param> 12 protected virtual void RaisePropertyChangedEvent(string propertyName) 13 { 14 ///一般写法 15 // PropertyChangedEventHandler handler = this.PropertyChanged; 16 // if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 17 ///简易写法 18 PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 19 } 20 }
2,前台XAML代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <Grid VerticalAlignment="Center" HorizontalAlignment="Center"> 2 <Grid.RowDefinitions> 3 <RowDefinition></RowDefinition> 4 <RowDefinition></RowDefinition> 5 </Grid.RowDefinitions> 6 <Grid> 7 <ItemsControl Grid.Row="1" Margin="15 30 30 20" x:Name="IT" VerticalAlignment="CENTER" HorizontalAlignment="center" ItemsSource="{Binding SettingListsSingle}" Visibility="visiBLE"> 8 <ItemsControl.ItemsPanel> 9 <ItemsPanelTemplate> 10 <StackPanel Orientation="Vertical" ></StackPanel> 11 </ItemsPanelTemplate> 12 </ItemsControl.ItemsPanel> 13 <ItemsControl.ItemTemplate> 14 <DataTemplate> 15 <Grid > 16 <Grid.ColumnDefinitions> 17 <ColumnDefinition Width="100"></ColumnDefinition> 18 <ColumnDefinition Width="AUTO"></ColumnDefinition> 19 </Grid.ColumnDefinitions> 20 <Grid Background="Brown" Tag="itgrid" x:Name="gr" Margin="0 0 5 0"> 21 <Border BorderBrush="#FF00FF68" BorderThickness="0 0 0 2"> 22 <TextBlock VerticalAlignment="Center" FontSize="16" Foreground="White" Text="{Binding Name}" TextBlock.TextAlignment="Center"></TextBlock> 23 </Border> 24 </Grid> 25 <ItemsControl x:Name="rowitems" Tag="{Binding GroupName}" HorizontalAlignment="Left" ItemsSource="{Binding TgLists}" Grid.Column="1" Margin="0 0 0 0"> 26 <ItemsControl.ItemsPanel> 27 <ItemsPanelTemplate> 28 <StackPanel Orientation="Horizontal"></StackPanel> 29 </ItemsPanelTemplate> 30 </ItemsControl.ItemsPanel> 31 <ItemsControl.ItemTemplate> 32 <DataTemplate> 33 <Grid> 34 <Border BorderBrush="#437DE5" BorderThickness="0 0 0 2" Padding="2"> 35 <ToggleButton Visibility="Visible" Command="{Binding CheckedCommand}" Margin="0" FontSize="15" CommandParameter="{Binding DataContext.GroupName,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ItemsControl}}" IsChecked="{Binding IsChecked}" MaxWidth="200" Style="{DynamicResource ToggleButtonStyle}" > 36 <ToggleButton.Resources> 37 <local:ParmsConverter x:Key="pc"></local:ParmsConverter> 38 </ToggleButton.Resources> 39 <ToggleButton.Content> 40 <TextBlock x:Name="tbcontent" TextWrapping="Wrap" Text="{Binding Content}"> 41 </TextBlock> 42 </ToggleButton.Content> 43 </ToggleButton> 44 </Border> 45 </Grid> 46 </DataTemplate> 47 </ItemsControl.ItemTemplate> 48 </ItemsControl> 49 </Grid> 50 </DataTemplate> 51 </ItemsControl.ItemTemplate> 52 </ItemsControl> 53 </Grid> 54 55 <ItemsControl Grid.Row="1" Margin="15 30 30 20" x:Name="IT2" VerticalAlignment="CENTER" HorizontalAlignment="CENTER" ItemsSource="{Binding SettingLists}" Visibility="visiBLE"> 56 <ItemsControl.ItemsPanel> 57 <ItemsPanelTemplate> 58 <StackPanel Orientation="Vertical" ></StackPanel> 59 </ItemsPanelTemplate> 60 </ItemsControl.ItemsPanel> 61 <ItemsControl.ItemTemplate> 62 <DataTemplate> 63 <Grid > 64 <Grid.ColumnDefinitions> 65 <ColumnDefinition Width="100"></ColumnDefinition> 66 <ColumnDefinition Width="AUTO"></ColumnDefinition> 67 </Grid.ColumnDefinitions> 68 <Grid Background="#437DE5" Tag="itgrid" x:Name="gr" Margin="0 0 5 0"> 69 <Border BorderBrush="#FF00FF68" BorderThickness="0 0 0 2"> 70 <TextBlock VerticalAlignment="Center" FontSize="16" Foreground="White" Text="{Binding Name}" TextBlock.TextAlignment="Center"></TextBlock> 71 </Border> 72 </Grid> 73 <ItemsControl x:Name="rowitems" Tag="{Binding GroupName}" HorizontalAlignment="Left" ItemsSource="{Binding TgLists}" Grid.Column="1" Margin="0 0 0 0"> 74 <ItemsControl.ItemsPanel> 75 <ItemsPanelTemplate> 76 <StackPanel Orientation="Horizontal"></StackPanel> 77 </ItemsPanelTemplate> 78 </ItemsControl.ItemsPanel> 79 <ItemsControl.ItemTemplate> 80 <DataTemplate> 81 <Grid> 82 <Border BorderBrush="#437DE5" BorderThickness="0 0 0 2" Padding="2"> 83 <ToggleButton Visibility="Visible" Command="{Binding CheckedCommand}" Margin="0" FontSize="15" CommandParameter="{Binding DataContext.GroupName,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ItemsControl}}" IsChecked="{Binding IsChecked}" MaxWidth="120" Style="{DynamicResource ToggleButtonStyle}" > 84 <ToggleButton.Resources> 85 <local:ParmsConverter x:Key="pc"></local:ParmsConverter> 86 </ToggleButton.Resources> 87 <!--<ToggleButton.CommandParameter> 88 <MultiBinding Converter="{StaticResource pc}"> 89 <Binding Path="."></Binding> 90 <Binding Path="DataContext.GroupName" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=ItemsControl}"></Binding> 91 </MultiBinding> 92 </ToggleButton.CommandParameter>--> 93 <ToggleButton.Content> 94 <TextBlock x:Name="tbcontent" TextWrapping="Wrap" Text="{Binding Content}"> 95 </TextBlock> 96 </ToggleButton.Content> 97 </ToggleButton> 98 99 100 101 </Border> 102 <!--<Border BorderBrush="#437DE5" BorderThickness="0 0 0 2" Padding="2"> 103 <RadioButton GroupName="{Binding Tag,ElementName=rowitems}" Checked="ToggleButton_Checked" Margin="0" FontSize="15" IsChecked="{Binding IsChecked}" MaxWidth="300" Content="{Binding Content}" Style="{DynamicResource ToggleButtonStyle}" /> 104 </Border>--> 105 </Grid> 106 </DataTemplate> 107 </ItemsControl.ItemTemplate> 108 </ItemsControl> 109 </Grid> 110 </DataTemplate> 111 </ItemsControl.ItemTemplate> 112 </ItemsControl> 113 </Grid>
使用的主要样式如下:(一般用Blend完成,这里加入了2个进入和退场动画)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <Style x:Key="ToggleButtonStyle" TargetType="{x:Type ToggleButton}"> 2 <!--<Setter Property="MaxHeight" Value="></Setter>--> 3 <Setter Property="Template"> 4 <Setter.Value> 5 <ControlTemplate TargetType="{x:Type ToggleButton}"> 6 <ControlTemplate.Resources> 7 <SolidColorBrush x:Key="pathcolor" Color="#FF21A621"></SolidColorBrush> 8 <SolidColorBrush x:Key="buttonuncheckedcolor" Color="#FF767A76"></SolidColorBrush> 9 <SolidColorBrush x:Key="buttoncheckedcolor"></SolidColorBrush> 10 <SolidColorBrush x:Key="headercolor"></SolidColorBrush> 11 <Storyboard x:Key="Unchecked"> 12 <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)" Storyboard.TargetName="grid"> 13 <EasingColorKeyFrame KeyTime="0" Value="#FF21A621"/> 14 <EasingColorKeyFrame KeyTime="0:0:0.3" Value="sc#1, 0.114781961, 0.269301116, 0.114781961"/> 15 <EasingColorKeyFrame KeyTime="0:0:0.5" Value="Gray"/> 16 </ColorAnimationUsingKeyFrames> 17 <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="br"> 18 <EasingDoubleKeyFrame KeyTime="0" Value="0"/> 19 <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="30"/> 20 </DoubleAnimationUsingKeyFrames> 21 <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="br"> 22 <EasingDoubleKeyFrame KeyTime="0" Value="20"/> 23 <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="0"/> 24 </DoubleAnimationUsingKeyFrames> 25 <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="br"> 26 <EasingDoubleKeyFrame KeyTime="0" Value="20"/> 27 <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="0"/> 28 </DoubleAnimationUsingKeyFrames> 29 <ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Margin)" Storyboard.TargetName="br"> 30 <EasingThicknessKeyFrame KeyTime="0" Value="5,2"/> 31 <EasingThicknessKeyFrame KeyTime="0:0:0.3" Value="0,2"/> 32 </ThicknessAnimationUsingKeyFrames> 33 <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="checkBox"> 34 <EasingDoubleKeyFrame KeyTime="0" Value="100"/> 35 <EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="0"/> 36 <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="0"/> 37 </DoubleAnimationUsingKeyFrames> 38 <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="br"> 39 <EasingDoubleKeyFrame KeyTime="0" Value="1"/> 40 <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="1"/> 41 </DoubleAnimationUsingKeyFrames> 42 <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="br"> 43 <EasingDoubleKeyFrame KeyTime="0" Value="1"/> 44 <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="1"/> 45 </DoubleAnimationUsingKeyFrames> 46 </Storyboard> 47 <Storyboard x:Key="Checked"> 48 <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)" Storyboard.TargetName="grid"> 49 <SplineColorKeyFrame KeyTime="0" Value="#FF767A76"/> 50 <SplineColorKeyFrame KeyTime="0:0:0.2" Value="sc#1, 0.114781961, 0.269301116, 0.114781961"/> 51 <SplineColorKeyFrame KeyTime="0:0:0.5" Value="#FF21A621"/> 52 </ColorAnimationUsingKeyFrames> 53 <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="br"> 54 <SplineDoubleKeyFrame KeyTime="0" Value="30"/> 55 <SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="0"/> 56 </DoubleAnimationUsingKeyFrames> 57 <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="br"> 58 <SplineDoubleKeyFrame KeyTime="0" Value="0"/> 59 <SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="20"/> 60 </DoubleAnimationUsingKeyFrames> 61 <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="br"> 62 <SplineDoubleKeyFrame KeyTime="0" Value="0"/> 63 <SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="20"/> 64 </DoubleAnimationUsingKeyFrames> 65 <ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Margin)" Storyboard.TargetName="br"> 66 <SplineThicknessKeyFrame KeyTime="0" Value="0,2"/> 67 <SplineThicknessKeyFrame KeyTime="0:0:0.4" Value="5,2"/> 68 </ThicknessAnimationUsingKeyFrames> 69 <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="checkBox"> 70 <SplineDoubleKeyFrame KeyTime="0" Value="0"/> 71 <SplineDoubleKeyFrame KeyTime="0:0:0.3" Value="0"/> 72 <SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="100"/> 73 </DoubleAnimationUsingKeyFrames> 74 <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="br"> 75 <SplineDoubleKeyFrame KeyTime="0" Value="1"/> 76 <SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="1"/> 77 </DoubleAnimationUsingKeyFrames> 78 <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="br"> 79 <SplineDoubleKeyFrame KeyTime="0" Value="1"/> 80 <SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="1"/> 81 </DoubleAnimationUsingKeyFrames> 82 </Storyboard> 83 </ControlTemplate.Resources> 84 <Grid x:Name="grid" Height="AUTO" Width="AUTO" Background="{StaticResource buttonuncheckedcolor}"> 85 <Grid.ColumnDefinitions> 86 <ColumnDefinition Width="*"></ColumnDefinition> 87 <ColumnDefinition Width="AUTO"></ColumnDefinition> 88 </Grid.ColumnDefinitions> 89 <Border Padding="5"> 90 <Label TextElement.Foreground="WHITE" Content="{TemplateBinding Content}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center" Margin="0 0 0 0" MaxWidth="{TemplateBinding MaxWidth}"/> 91 </Border> 92 <Border Grid.Column="1" Opacity="1" x:Name="br" VerticalAlignment="CENTER" HorizontalAlignment="CENTER" Margin="0 2" BorderThickness="2" Background="White" CornerRadius="15" RenderTransformOrigin="0.5,0.5" Height="0" Width="0" > 93 <Border.RenderTransform> 94 <TransformGroup> 95 <ScaleTransform ScaleX="0" ScaleY="0"/> 96 <SkewTransform/> 97 <RotateTransform/> 98 <TranslateTransform/> 99 </TransformGroup> 100 </Border.RenderTransform> 101 <Path Margin="2" x:Name="checkBox" UseLayoutRounding="False" Stretch="Fill" Opacity="100" Fill="{StaticResource pathcolor}" Data="M 1145.607177734375,430 C1145.607177734375,430 1141.449951171875,435.0772705078125 1141.449951171875,435.0772705078125 1141.449951171875,435.0772705078125 1139.232177734375,433.0999755859375 1139.232177734375,433.0999755859375 1139.232177734375,433.0999755859375 1138,434.5538330078125 1138,434.5538330078125 1138,434.5538330078125 1141.482177734375,438 1141.482177734375,438 1141.482177734375,438 1141.96875,437.9375 1141.96875,437.9375 1141.96875,437.9375 1147,431.34619140625 1147,431.34619140625 1147,431.34619140625 1145.607177734375,430 1145.607177734375,430 z"/> 102 </Border> 103 104 </Grid> 105 <ControlTemplate.Triggers> 106 <!--<EventTrigger RoutedEvent="FrameworkElement.Loaded"> 107 <BeginStoryboard Storyboard="{StaticResource Unchecked_Copy2}"/> 108 </EventTrigger>--> 109 <Trigger Property="IsChecked" Value="true"> 110 <Trigger.EnterActions> 111 <BeginStoryboard Storyboard="{StaticResource Checked}"></BeginStoryboard> 112 </Trigger.EnterActions> 113 <Trigger.ExitActions> 114 <BeginStoryboard Storyboard="{StaticResource Unchecked}"></BeginStoryboard> 115 </Trigger.ExitActions> 116 </Trigger> 117 <!--<EventTrigger RoutedEvent="ToggleButton.Unchecked"> 118 <BeginStoryboard Storyboard="{StaticResource Unchecked}"/> 119 </EventTrigger> 120 <EventTrigger RoutedEvent="ToggleButton.Checked"> 121 <BeginStoryboard x:Name="Unchecked_Copy2_BeginStoryboard" Storyboard="{StaticResource Unchecked_Copy2}"/> 122 </EventTrigger>--> 123 </ControlTemplate.Triggers> 124 </ControlTemplate> 125 </Setter.Value> 126 </Setter> 127 </Style>
样式和颜色都是根据自己喜好来的,可以随意修改的。关键点事要用Path画出选中的钩,然后通过数据触发器将选中和不选中的姿态通过动画来展示:
<Trigger Property="IsChecked" Value="true">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource Checked}"></BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource Unchecked}"></BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
3,定义ViewModel和相关结构:
首先是定义选中的3个状态:多行多选,多行单选,以及单行单选。(其它类型请自行添加和实现。)
public enum CheckType
{
MutilChecked,
SingleChecked,
RowChecked
}
然后是 设计层次结构:通用来讲我这里粗略的设计成嵌套类型,即数据源为List<setmodel>类型,而setmodel中又包含ObservableCollection<tgmodel>类型,而这个tgmodel呢,其实就是精确到的每一个按钮对应的模型了。下面给出具体定义:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class setmodel : ModelBase 2 { 3 private string _name; 4 /// <summary> 5 /// 显示名称 6 /// </summary> 7 public string Name 8 { 9 get { return _name; } 10 set 11 { 12 _name = value; 13 RaisePropertyChangedEvent("Name"); 14 } 15 } 16 17 private string _groupname = "singlecheck"; 18 /// <summary> 19 /// 显示名称 20 /// </summary> 21 public string GroupName 22 { 23 get { return _groupname; } 24 set 25 { 26 _groupname = value; 27 RaisePropertyChangedEvent("GroupName"); 28 } 29 } 30 public ObservableCollection<tgmodel> TgLists { get; set; } 31 32 33 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class tgmodel : ModelBase 2 { 3 public tgmodel() 4 { 5 CommandDefine = new CommandDefine(); 6 } 7 private string content; 8 /// <summary> 9 /// Toggle按钮显示内容 10 /// </summary> 11 public string Content 12 { 13 get { return content; } 14 set 15 { 16 content = value; 17 RaisePropertyChangedEvent("Content"); 18 } 19 } 20 21 22 private bool ischecked; 23 /// <summary> 24 /// 是否选中 25 /// </summary> 26 public bool IsChecked 27 { 28 get { return ischecked; } 29 set 30 { 31 ischecked = value; 32 RaisePropertyChangedEvent("IsChecked"); 33 } 34 } 35 public ICommand CheckedCommand { get; set; } 36 public CommandDefine CommandDefine { get; set; } 37 }
然后这里写了一个队togglebutton 信息的辅助类:主要是封装了togglebutton对应的模型 TgModel,它所在组的 上一级模型 SetModel,所在行的名称 RowName。
public class TgInfo
{
public tgmodel TgModel { get; set; }
public setmodel SetModel { get; set; }
public string RowName { get; set; }
//public CheckType CheckType { get; set; }
//public List<setmodel> SourceLists { get; set; }
}
4,最后就是功能的实现了,这里代码有点乱,还有进一步修改的可能。
(1)初始化DataContext,先是ViewModel:
SettingListsSingle 是我上面单行拿来做选择项的集合,下面的三行数据数据源则是
SettingLists。
1 public class ViewModel : ModelBase 2 { 3 /// <summary> 4 /// 设置列表 5 /// </summary> 6 public List<setmodel> SettingLists { get; set; } 7 public List<setmodel> SettingListsSingle { get; set; } 8 9 private CheckType _checktype; 10 /// <summary> 11 /// 选项类型 12 /// </summary> 13 public CheckType CheckType 14 { 15 get { return _checktype; } 16 set 17 { 18 _checktype = value; 19 RaisePropertyChangedEvent("CheckType"); 20 } 21 } 22 23 private CheckType _testchecktype; 24 /// <summary> 25 /// 选项类型 26 /// </summary> 27 public CheckType TestCheckType 28 { 29 get { return _testchecktype; } 30 set 31 { 32 _testchecktype = value; 33 RaisePropertyChangedEvent("TestCheckType"); 34 } 35 } 36 37 }
初始化ViewModel,后台代码:
1 DataContext = new ViewModel() 2 { 3 TestCheckType = CheckType.SingleChecked, 4 SettingListsSingle = new List<setmodel>() { 5 new setmodel() { 6 GroupName="GN0", 7 Name="选中类型", 8 TgLists =new ObservableCollection<tgmodel>() 9 { new tgmodel() { Content="多选"}, 10 new tgmodel() { Content="行单选"}, 11 new tgmodel() { Content="全部单选" ,IsChecked=true }, 12 }}, }, 13 CheckType = CheckType.RowChecked, 14 SettingLists = new List<setmodel>() { 15 new setmodel() { 16 GroupName="GN1", 17 Name="测试数字", 18 TgLists =new ObservableCollection<tgmodel>() 19 { new tgmodel() { Content="Test1"}, 20 new tgmodel() { Content="Test2"}, 21 new tgmodel() { Content="Test3"}, 22 new tgmodel() { Content="Test4"}, 23 new tgmodel() { Content="Test5",IsChecked=true}, 24 }}, 25 new setmodel() { 26 GroupName ="GN2", 27 Name="测试字母", 28 TgLists =new ObservableCollection<tgmodel>() 29 { new tgmodel() { Content="TestA"}, 30 new tgmodel() { Content="TestB"}, 31 new tgmodel() { Content="TestC"}, 32 new tgmodel() { Content="TestD"}, 33 new tgmodel() { Content="TestE",IsChecked=true}, 34 }}, 35 new setmodel() { 36 GroupName="GN3", 37 Name="测试假名", 38 TgLists =new ObservableCollection<tgmodel>() 39 { new tgmodel() { Content="Testあ"}, 40 new tgmodel() { Content="Testい"}, 41 new tgmodel() { Content="Testう"}, 42 new tgmodel() { Content="Testえ"}, 43 new tgmodel() { Content="Testお",IsChecked=true}, 44 }}, 45 } 46 };
最后是命令的初始化:
1 var Vm = (DataContext as ViewModel); 2 3 Vm.SettingLists.ForEach(setmodel => setmodel.TgLists.ToList().ForEach( 4 (tgmodel=> tgmodel.CheckedCommand = new RelayCommand((pars) => 5 { 6 TgInfo info = new TgInfo 7 { 8 RowName = pars.ToString(), 9 SetModel = setmodel, 10 TgModel = tgmodel 11 }; 12 SetTgStatus(info, Vm,Vm.CheckType, Vm.SettingLists); 13 })))); 14 15 16 17 Vm.SettingListsSingle.ForEach(setmodel => setmodel.TgLists.ToList().ForEach( 18 (tgmodel => tgmodel.CheckedCommand = new RelayCommand((pars) => 19 { 20 TgInfo info = new TgInfo 21 { 22 RowName = pars.ToString(), 23 SetModel = setmodel, 24 TgModel = tgmodel 25 }; 26 SetTgStatus(info, Vm, Vm.TestCheckType, Vm.SettingListsSingle); 27 }))));
设置命令实现如下:这里只是我的实现。
1 /// <summary> 2 /// 设置选中状态 3 /// </summary> 4 /// <param name="pars"></param> 5 /// <param name="Vm"></param> 6 private void SetTgStatus(params object[] parms) 7 { 8 var tginfo = parms[0] as TgInfo; 9 var tgmodel = tginfo.TgModel; 10 var rowname = tginfo.RowName; 11 var setmodel = tginfo.SetModel; 12 var Vm = parms[1] as ViewModel; 13 var checktype = (CheckType)parms[2]; 14 var settings = parms[3] as List<setmodel>; 15 if (setmodel.Name=="选中类型") 16 { 17 var index = setmodel.TgLists.IndexOf(tgmodel); 18 Vm.CheckType = this[index]; 19 } 20 if (checktype == CheckType.RowChecked) 21 { 22 settings.ForEach(sets => 23 sets.TgLists.Where 24 (t => rowname == sets.GroupName&& t!=tgmodel).ToList(). 25 ForEach(tg => tg.IsChecked = false)); 26 } 27 else if (checktype == CheckType.SingleChecked) 28 { 29 settings.ForEach(sets => 30 sets.TgLists.Where(t=>t!=tgmodel).ToList(). 31 ForEach(tg => tg.IsChecked = false)); 32 } 33 else 34 { 35 36 } 37 }
其中CheckType 用到了索引器,实现如下:
1 public CheckType this[int index] 2 { 3 get 4 { 5 return index == 0 ? CheckType.MutilChecked : 6 (index == 1 ? CheckType.RowChecked : 7 CheckType.SingleChecked); 8 } 9 10 set 11 { 12 } 13 }
5,运行,OK。有什么问题可以一起讨论!
现在开始坚持每天一贴!也算是项目经验的总结和分享吧。当然肯定有很多不足之处,希望大家多多指教!