原地址: http://www.cnblogs.com/yk250/p/5660340.html

效果图如下:支持分组的单选框,复选框样式和MVVM下功能的实现。这是项目中一个快捷键功能的扩展。

1,准备工作:VS2015 (15对WPF的支持变得异常的好,调试模式下允许自动更改属性。),随VS发布的Blend,几个基础类:

  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. /// <summary>
  40. /// Initializes a new instance of the RelayCommand class that
  41. /// can always execute.
  42. /// </summary>
  43. /// <param name="execute">The execution logic.</param>
  44. /// <exception cref="ArgumentNullException">If the execute argument is null.</exception>
  45. public RelayCommand(Action execute)
  46. : this(execute, null)
  47. {
  48. }
  49.  
  50. /// <summary>
  51. /// Initializes a new instance of the RelayCommand class.
  52. /// </summary>
  53. /// <param name="execute">The execution logic.</param>
  54. /// <param name="canExecute">The execution status logic.</param>
  55. /// <exception cref="ArgumentNullException">If the execute argument is null.</exception>
  56. public RelayCommand(Action execute, Func<bool> canExecute)
  57. {
  58. if (execute == null)
  59. {
  60. throw new ArgumentNullException("execute");
  61. }
  62.  
  63. _execute = execute;
  64. _canExecute = canExecute;
  65. }
  66.  
  67. #endregion
  68.  
  69. #region ICommand Members
  70.  
  71. public bool CanExecute(object parameter)
  72. {
  73. if (parameter == null)
  74. {
  75. return _canExecute == null ? true : _canExecute();
  76. }
  77.  
  78. return _canExecutePre == null ? true : _canExecutePre(parameter);
  79. }
  80.  
  81. public event EventHandler CanExecuteChanged
  82. {
  83. add { CommandManager.RequerySuggested += value; }
  84. remove { CommandManager.RequerySuggested -= value; }
  85. }
  86.  
  87. public void Execute(object parameter)
  88. {
  89. if (!CanExecute(parameter))
  90. return;
  91. if (parameter == null)
  92. {
  93. if (_execute != null)
  94. _execute();
  95. return;
  96. }
  97. if (_executeAct != null)
  98. _executeAct(parameter);
  99.  
  100. }
  101.  
  102. #endregion
  103. }
  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代码如下:

  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. </Border>
  100. <!--<Border BorderBrush="#437DE5" BorderThickness="0 0 0 2" Padding="2">
  101. <RadioButton GroupName="{Binding Tag,ElementName=rowitems}" Checked="ToggleButton_Checked" Margin="0" FontSize="15" IsChecked="{Binding IsChecked}" MaxWidth="300" Content="{Binding Content}" Style="{DynamicResource ToggleButtonStyle}" />
  102. </Border>-->
  103. </Grid>
  104. </DataTemplate>
  105. </ItemsControl.ItemTemplate>
  106. </ItemsControl>
  107. </Grid>
  108. </DataTemplate>
  109. </ItemsControl.ItemTemplate>
  110. </ItemsControl>
  111. </Grid>

使用的主要样式如下:(一般用Blend完成,这里加入了2个进入和退场动画)

  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呢,其实就是精确到的每一个按钮对应的模型了。下面给出具体定义:

  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. }
  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. private bool ischecked;
  22. /// <summary>
  23. /// 是否选中
  24. /// </summary>
  25. public bool IsChecked
  26. {
  27. get { return ischecked; }
  28. set
  29. {
  30. ischecked = value;
  31. RaisePropertyChangedEvent("IsChecked");
  32. }
  33. }
  34. public ICommand CheckedCommand { get; set; }
  35. public CommandDefine CommandDefine { get; set; }
  36. }

然后这里写了一个队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:

  1. SettingListsSingle 是我上面单行拿来做选择项的集合,下面的三行数据数据源则是
  1. 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. Vm.SettingListsSingle.ForEach(setmodel => setmodel.TgLists.ToList().ForEach(
  16. (tgmodel => tgmodel.CheckedCommand = new RelayCommand((pars) =>
  17. {
  18. TgInfo info = new TgInfo
  19. {
  20. RowName = pars.ToString(),
  21. SetModel = setmodel,
  22. TgModel = tgmodel
  23. };
  24. SetTgStatus(info, Vm, Vm.TestCheckType, Vm.SettingListsSingle);
  25. }))));

设置命令实现如下:这里只是我的实现。

  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[] as TgInfo;
  9. var tgmodel = tginfo.TgModel;
  10. var rowname = tginfo.RowName;
  11. var setmodel = tginfo.SetModel;
  12. var Vm = parms[] as ViewModel;
  13. var checktype = (CheckType)parms[];
  14. var settings = parms[] 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 == ? CheckType.MutilChecked :
  6. (index == ? CheckType.RowChecked :
  7. CheckType.SingleChecked);
  8. }
  9.  
  10. set
  11. {
  12. }
  13. }

5,运行,OK。有什么问题可以一起讨论!

现在开始坚持每天一贴!也算是项目经验的总结和分享吧。当然肯定有很多不足之处,希望大家多多指教!

可分组的选择框控件(MVVM下)(Toggle样式 仿造单选框RadioButton,复选框CheckBox功能)的更多相关文章

  1. Qt树形控件QTreeView使用1——节点的添加删除操作 复选框的设置

    QtreeView是ui中最常用的控件,Qt中QTreeWidget比QTreeView更简单,但没有QTreeView那么灵活(QTreeWidget封装的和MFC的CTreeCtrl很类似,没有m ...

  2. MFC的组合框(ComboBox)控件切换下拉样式

    由于课题的需求需要做MFC串口程序,看了百度下载的串口助手的界面风格,发现这个设计很好 波特率的组合框只给出了5个可选数值,然后第6个选项是Custom,即手动输入. 实际上DCB结构的BaudRat ...

  3. checkbox复选框和div click事件重叠,点击div后复选框也被选中,同时改变div颜色,否则则不选中

     checkbox复选框和div click事件重叠,点击div后复选框也被选中,同时改变div颜色,否则则不选中 <!DOCTYPE html> <html lang=" ...

  4. bootstrap-multiselect 设置单选无效(设置单选依然是复选框)

    bootstrap-multiselect 的使用介绍:https://www.cnblogs.com/landeanfen/p/5013452.html bootstrap-multiselect ...

  5. bootstrap table 复选框选中后,翻页不影响已选中的复选框

    使用的 jquery版本为 2.1.1 在项目中发现bootstrap table的复选框选中后,翻页操作会导致上一页选中的丢失,api中的 bootstrapTable('getSelections ...

  6. Android_(控件)使用AlertDialog实现点击Button显示出多选框

    单击"更多"按钮,显示出多选框 运行截图: 程序结构 (本想通过Button中android:background使用drawable资源下的图片作为按钮背景,设计太丑就去掉了Σ( ...

  7. css 设置 checkbox复选框控件的对勾√样式

      效果 最终的样式,想要的效果:   我们要创建方框中的对勾,对于这一点,我们可以使用:after伪类创建一个新的元素,为了实现这个样式,我们可以创建一个5px * 15px的长方形并给他加上边框. ...

  8. Qt — tableWidget插入复选框

    之前不太了解Qt中的相关控件,一直尝试直接在tableview上增加复选框. 但相对来说,在tableview增加复选框的工作量与麻烦程度远超tableWidget. 接下来是如何在Qt的tableW ...

  9. 关于bootstrap--表单(下拉<select>、输入框<input>、文本域<textare>复选框<checkbox>和单选按钮<radio>)

    html 里面的 role 本质上是增强语义性,当现有的HTML标签不能充分表达语义性的时候,就可以借助role来说明.通常这种情况出现在一些自定义的组件上,这样可增强组件的可访问性.可用性和可交互性 ...

随机推荐

  1. 集合视图 UICollectionView

    什么是UICollectionView UICollectionView是一种新的数据展示方式,简单来说可以把他理解成多列的UITableView(请一定注意这是UICollectionView的最最 ...

  2. SpringMVC,3种不同的URL路由配置方法

    1. 先说说一种比较常见的: <servlet> <servlet-name>theDispatcher</servlet-name> <servlet-cl ...

  3. ORACLE 数据库 MOD 函数用法

    1.求2和1的余数. Select mod(2,1) from dual: 2能被1整除所以余数为0. 2.MOD(x,y)返回X除以Y的余数.如果Y是0,则返回X的值. Select mod(2,0 ...

  4. java播放背景音乐的几种方式

    大四第一学期快结束了,准备找实习单位的时候,用了一周的时间去投简历去面试,结果没有一家有反馈要不就是面试没通过,拿着iOS的项目(在老师工作室的外包项目)去面试java开发,结果全部碰壁. 第一种,直 ...

  5. Codeforces Round #174 (Div. 2)

    A. Cows and Primitive Roots 暴力. B. Cows and Poker Game 模拟. C. Cows and Sequence 线段树维护. D. Cow Progra ...

  6. VS2010遇到fatal error C1083: 无法打开预编译头文件:“xxx.pch”: No such file or directory

    对C++和VS2010非常不熟悉,但是无奈赶着项目,只能看了点基础就上手,然后就碰到这个问题了. 原因分析: http://bbs.csdn.net/topics/340191697?page=1 编 ...

  7. [原创]cocos2d-x研习录-第三阶 特性之粒子系统

    我想接触过游戏引擎的同学,对粒子系统应该不会陌生.它用于解决由大量按一定规则运动(变化)的微小物质在计算机上的生成和显示问题.粒子系统在游戏中有着非常广泛的应用,可以模拟很多现象,如火花.爆炸.烟雾. ...

  8. C#-2 wpf 项目编程结构设计

    View:界面布局 EXCEL ViewModel:流程,数据粘合胶水 Model: 1)DB 结构 (数据库结构) 2)绑定的数据(界面交互数据) Service:1)BLL(画流程图)画业务逻辑图 ...

  9. 自定义滚动条 - mCustomScrollbar

    项目中需要使用自定义滚动条,但是试用了很多都功能不够全,今天发现一个比较全而且用法很简单的 -- mCustomScrollbar http://manos.malihu.gr/jquery-cust ...

  10. MYCAT介绍(转)

    从定义和分类来看,它是一个开源的分布式数据库系统,是一个实现了MySQL协议的服务器,前端用户可以把它看作是一个数据库代理,用MySQL客户端工具和命令行访问,而其后端可以用MySQL原生协议与多个M ...