动态绑定多个组合框以禁用选定的源项



这是我的第一篇文章。。。所以我希望我做得对。我正在使用C#、WPF,并试图遵循MVVM模式。诚然,我还有很多东西要学,但在过去的一年里我一直在进步。我将感谢对我发布的代码的任何其他评论,以帮助我学习。

目标:将多个(3到5个)组合框的源项绑定到同一个可观察集合,要求可观察集合中的任何项只能使用一次。如果在一个组合框中选择了一个项目,则该项目将被所有其他组合框禁用

研究:在我的搜索中,我发现了两个帖子:

C#具有相同项目的多个组合框源

您应该了解一下MVVM模式和ICollectionView。当你至少不了解MVVM时,这很容易实现,但很难解释强大的巴达博姆2017年7月3日12:42

具有共享绑定的多个组合框-从框中首次选择后显示错误

或者你可以再使用一点MVVM:如果是我,我会在一个模板化的ItemsControl中创建一系列ComboBoxes,该控件绑定到某个具有SelectedPort属性的类的集合,我也会为这些项使用一个自定义类,这只是一件简单的事情,使用StringPortName和boolIsPortEnabled。我会将IsPortEnabled绑定到XAML中的ComboBoxItem.IsEnabled。代码会少很多,但从概念上来说,这是一个很大的飞跃。如果你感兴趣,我们可以去那里——2016年7月12日13:27 Ed Plunkett

发布问题的个人没有概述或要求MVVM的上述答案之一。我感兴趣的是"从概念上跳一跳",学习如何优雅地做到这一点。

UI功能:我正在编写的应用程序接受用户的输入,以执行不同类型的地形特征折线的分析。有两种分析模式(两个单选按钮)需要不同的输入(启用/禁用功能选择的分组框)。

现在,我有多达5个组合框,它们绑定到源项的同一个可观察集合。分析模式1或模式2需要"功能0"组合框,其中包括功能1至功能3组合框,以及可选的功能4组合框(用于模式1)。

现在,在这种背景下,要求可观察集合中的任何项目只能用于功能0-4组合框或功能0和功能5-6组合框一次(请参见图像WPF UI示例)。我不知道如何获取一组已启用的组合框,当其中任何一个组合框发生更改时,获取所选项目并从其他组合框禁用该源项目。

例如,如果在"Feature0"组合框中选择了"Layer_0",则应禁用Feature1-4组合框中的"Layer_ 0"源项目,这样用户就无法在其他组合框中选中此项目。

以下是我认为需要完成的项目:

  1. combobox_SelectedIndexChanged的事件处理程序-绑定到FeaturesView.xaml和FeaturesViewModel.cs中的combobox。是否可以使用一个事件事件处理程序(仍在研究中)
  2. 如何维护已启用控件的选定项的源项列表,并禁用源项列表中的所有选定项

如能为我指明正确方向,我们将不胜感激。

下面的代码文件-你会在下面找到我迄今为止使用UI的不同项目文件。显然,不起作用的部分是禁用选定的特征名称。

主窗口.xaml

<Window
x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp1"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views="clr-namespace:WpfApp1.Views"
Title="MainWindow"
Width="300"
Height="450"
mc:Ignorable="d">
<Grid>
<views:FeatureView />
</Grid>
</Window>

功能View.xaml

<UserControl
x:Class="WpfApp1.Views.FeatureView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp1.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<UserControl.Resources>
<Style x:Key="MyRadioButtonTemplate" TargetType="RadioButton">
<Setter Property="Foreground" Value="Black" />
<Setter Property="Margin" Value="5" />
</Style>
<ControlTemplate x:Key="ComboWithHeader" TargetType="ContentControl">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label
Grid.Column="0"
Margin="2"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Content="{TemplateBinding Content}"
IsTabStop="False"
Target="comboBox" />
<ComboBox
x:Name="comboBox"
Grid.Column="1"
Margin="2"
IsEnabled="True"
IsTabStop="True"
ItemsSource="{Binding Path=Features, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
</ControlTemplate>
<BooleanToVisibilityConverter x:Key="BoolToVis" />
</UserControl.Resources>
<Grid>
<StackPanel Margin="5" Orientation="Vertical">
<GroupBox Header="Analysis Mode">
<Grid Margin="2" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<RadioButton
x:Name="Mode1"
Grid.Column="0"
Content="Mode 1"
IsChecked="True"
Style="{StaticResource MyRadioButtonTemplate}" />
<RadioButton
x:Name="Mode2"
Grid.Column="1"
Content="Mode2"
Style="{StaticResource MyRadioButtonTemplate}" />
</Grid>
</GroupBox>
<GroupBox Header="Line Selection">
<StackPanel>
<ContentControl
Name="Feature0"
Content="Feature 0"
Template="{StaticResource ComboWithHeader}" />
<Button
Width="60"
Margin="5"
HorizontalAlignment="Right"
Content="Select" />
</StackPanel>
</GroupBox>
<GroupBox
Header="Mode1 Layer Names"
IsEnabled="{Binding ElementName=Mode1, Path=IsChecked}"
Visibility="{Binding ElementName=Mode1, Path=IsChecked, Converter={StaticResource BoolToVis}}">
<StackPanel>
<ContentControl
Name="Feature1"
Content="Feature 1"
Template="{StaticResource ComboWithHeader}" />
<ContentControl
Name="Feature2"
Content="Feature 2"
Template="{StaticResource ComboWithHeader}" />
<ContentControl
Name="Feature3"
Content="Feature 3"
Template="{StaticResource ComboWithHeader}" />
<ContentControl
Name="Feature4"
Content="Feature 4"
Template="{StaticResource ComboWithHeader}"
Visibility="{Binding ElementName=IncludeFeature4, Path=IsChecked, Converter={StaticResource BoolToVis}}" />
<CheckBox
Name="IncludeFeature4"
Margin="2"
Content="Include Feature 4" />
</StackPanel>
</GroupBox>
<GroupBox
Header="Mode2 Layer Names"
IsEnabled="{Binding ElementName=Mode2, Path=IsChecked}"
Visibility="{Binding ElementName=Mode2, Path=IsChecked, Converter={StaticResource BoolToVis}}">
<StackPanel>
<ContentControl
Name="Feature5"
Content="Feature 5"
Template="{StaticResource ComboWithHeader}" />
<ContentControl
Name="Feature6"
Content="Feature 6"
Template="{StaticResource ComboWithHeader}" />
</StackPanel>
</GroupBox>
</StackPanel>
</Grid>
</UserControl>

FeatureView.xaml.cs

namespace WpfApp1.Views
{
using System.Windows.Controls;
using WpfApp1.ViewModels;
/// <summary>
/// Interaction logic for MultiComboBoxes.xaml
/// </summary>
public partial class FeatureView : UserControl
{
public FeatureView()
{
InitializeComponent();
this.DataContext = new FeatureViewModel();
}
}
}

功能模型.cs

namespace WpfApp1.Models
{
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
public class FeatureModel : INotifyPropertyChanged
{
private enum FeatureList
{
Layer_0,
Layer_1,
Layer_2,
Layer_3,
Layer_4,
Layer_5,
Layer_6
}
public ObservableCollection<string> Features = new ObservableCollection<string>(Enum.GetNames(typeof(FeatureList)));
private string featureName;
public string FeatureName
{
get
{
return featureName;
}
set
{
if (featureName != value)
{
featureName = value;
RaisePropertyChanged("FeatureName");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
}

FeatureViewModel.cs

namespace WpfApp1.ViewModels
{
using System.Collections.ObjectModel;
using System.ComponentModel;
using WpfApp1.Models;
public class FeatureViewModel : INotifyPropertyChanged
{
private ObservableCollection<string> AllFeatures { get; set; }
public ObservableCollection<string> Features { get; set; }
public FeatureViewModel()
{
FeatureModel featureModel = new FeatureModel();
Features = featureModel.Features;
AllFeatures = Features;
}
#region INotifyPropertyChanged Members
/// <summary>
/// Need to implement this interface in order to get data binding
/// to work properly.
/// </summary>
/// <param name="propertyName"></param>
private void NotifyPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion INotifyPropertyChanged Members
}
}

经过大量的尝试和错误,以及更多的在线研究,我发布了我的问题的部分解决方案。也许它将来会帮助其他人。

这个解决方案与最初的问题的不同之处在于我想如何实现它;然而,它确实提供了一个可行的解决方案。我看到这个实现的主要问题是,如果添加更多的组合框,它需要我认为是冗余的代码。

实施更改:

  1. 选择分析模式的单选按钮-与绑定的基本问题无关
  2. 禁用项目-虽然这会很好,但现在从列表中删除项目更容易
  3. 将多个组合框绑定到单个可观察集合被每个组合框的源项IEnumerable所取代
  4. 在每个组合框旁边添加一个按钮以"清除"所选项目

我确信有一种更好、更MVVM’ish的方法可以做到这一点(这是我希望通过发布这个问题来找到的),但在网上研究和阅读了许多主题试图找出答案后,由于缺乏专业知识,我没有成功。也许有专业知识的人可以适当地修改这个解决方案。

下面是使用四个组合框的代码有一项不能按我的意愿工作。空列表项用作,但从每个列表中删除选定项时,应忽略该空项(仍在为此寻找解决方案)。

主窗口.xaml:

<Window
x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:prop="clr-namespace:WpfApp1.Properties"
xmlns:views="clr-namespace:WpfApp1.Views"
Title="MainWindow"
Width="350"
Height="700"
mc:Ignorable="d">
<Grid>
<StackPanel>
<views:FeatureView />
</StackPanel>
</Grid>
</Window>

主窗口.xaml.cs:

using System;
using System.Windows;
namespace WpfApp1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}

FeatureView.xaml:

<UserControl
x:Class="WpfApp1.Views.FeatureView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ViewModels="clr-namespace:WpfApp1.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<UserControl.Resources>
<!--  MyComboBoxStyle  -->
<Style x:Key="MyComboBoxStyle" TargetType="{x:Type ComboBox}">
<Setter Property="Tag" Value="" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label
Grid.Column="0"
Width="Auto"
Margin="2"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Content="{TemplateBinding Tag}"
Foreground="Black"
IsTabStop="False" />
<ComboBox
Name="cmbBox"
Grid.Column="1"
Margin="2"
Foreground="Black"
ItemsSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ItemsSource}"
SelectedItem="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedItem}" />
<Button
Grid.Column="2"
Padding="2"
Command="{Binding OnComboBox_ClearSelection}"
CommandParameter="{Binding ElementName=cmbBox}"
Style="{DynamicResource MyButtonTemplate}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--  MyButtonTemplate  -->
<Style x:Key="MyButtonTemplate" TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="Black" />
<Setter Property="Margin" Value="5" />
<Setter Property="Height" Value="15" />
<Setter Property="Width" Value="15" />
<Setter Property="IsTabStop" Value="True" />
<Setter Property="IsEnabled" Value="True" />
<Setter Property="HorizontalAlignment" Value="Right" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Border
Name="border"
Padding="4,2"
Background="{TemplateBinding Background}"
BorderBrush="DarkGray"
BorderThickness="1"
CornerRadius="3">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<TextBlock Text="X"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="BorderBrush" Value="Black" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--  MyLabelTemplate  -->
<Style x:Key="MyLabelTemplate" TargetType="{x:Type Label}">
<Setter Property="Foreground" Value="Black" />
<Setter Property="Margin" Value="2" />
<Setter Property="Width" Value="Auto" />
<Setter Property="HorizontalAlignment" Value="Right" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="IsTabStop" Value="False" />
</Style>
<!--  MyTextBlockTemplate  -->
<Style x:Key="MyTextBlockTemplate" TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Black" />
<Setter Property="Margin" Value="2" />
<Setter Property="IsEnabled" Value="True" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</UserControl.Resources>

<!--  Main Layout  -->
<StackPanel Margin="5" Orientation="Vertical">
<!--  Feature 1  -->
<ComboBox
Name="Feature1View"
ItemsSource="{Binding Feature1Items}"
SelectedItem="{Binding Feature1SelectedValue}"
Style="{StaticResource MyComboBoxStyle}"
Tag="Feature 1" />
<!--  Feature 2  -->
<ComboBox
Name="Feature2View"
ItemsSource="{Binding Feature2Items}"
SelectedItem="{Binding Feature2SelectedValue}"
Style="{StaticResource MyComboBoxStyle}"
Tag="Feature 2" />

<!--  Feature 3  -->
<ComboBox
Name="Feature3View"
ItemsSource="{Binding Feature3Items}"
SelectedItem="{Binding Feature3SelectedValue}"
Style="{StaticResource MyComboBoxStyle}"
Tag="Feature 3" />
<!--  Feature 4  -->
<ComboBox
Name="Feature4View"
ItemsSource="{Binding Feature4Items}"
SelectedItem="{Binding Feature4SelectedValue}"
Style="{StaticResource MyComboBoxStyle}"
Tag="Feature 4" />
<Rectangle
Width="Auto"
Height="5"
Fill="#FFF4F4F5"
Stroke="Black" />
<!--  Feature 1 Selected  -->
<DockPanel>
<Label Content="Feature 1 Selected" Style="{StaticResource MyLabelTemplate}" />
<TextBlock
x:Name="Feature1Selected"
Style="{StaticResource MyTextBlockTemplate}"
Text="{Binding Feature1SelectedValue, Mode=OneWay}" />
</DockPanel>
<!--  Feature 2 Selected  -->
<DockPanel>
<Label Content="Feature 2 Selected" Style="{StaticResource MyLabelTemplate}" />
<TextBlock
x:Name="Feature2Selected"
Style="{StaticResource MyTextBlockTemplate}"
Text="{Binding Feature2SelectedValue, Mode=OneWay}" />
</DockPanel>
<!--  Feature 3 Selected  -->
<DockPanel>
<Label Content="Feature 3 Selected" Style="{StaticResource MyLabelTemplate}" />
<TextBlock
x:Name="Feature3Selected"
Style="{StaticResource MyTextBlockTemplate}"
Text="{Binding Feature3SelectedValue, Mode=OneWay}" />
</DockPanel>
<!--  Feature 4 Selected  -->
<DockPanel>
<Label Content="Feature 4 Selected" Style="{StaticResource MyLabelTemplate}" />
<TextBlock
x:Name="Feature4Selected"
Style="{StaticResource MyTextBlockTemplate}"
Text="{Binding Feature4SelectedValue, Mode=OneWay}" />
</DockPanel>
</StackPanel>
</UserControl>

FeatureView.xaml.cs:

namespace WpfApp1.Views
{
using System.Windows.Controls;
using WpfApp1.ViewModels;
/// <summary>
/// Interaction logic for MultiComboBoxes.xaml
/// </summary>
public partial class FeatureView : UserControl
{
public FeatureView()
{
InitializeComponent();
this.DataContext = new FeatureViewModel();
}
}
}

FeatureViewModel.cs:

namespace WpfApp1.ViewModels
{
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows.Controls;
using System.Windows.Input;
using WpfApp1.Models;
public class FeatureViewModel : INotifyPropertyChanged
{
#region Definitions
#region enum
private enum MyFeatureList
{
Layer_1,
Layer_2,
Layer_3,
Layer_4
}
#endregion enum
#region PrivateProperties
private readonly List<string> features = new List<string>();
#region AddFeatures
private ObservableCollection<Feature> AddFeatures
{
get
{
var features = new ObservableCollection<Feature>
{
// add blank feature
new Feature("", true)
};
foreach (var feature in Enum.GetNames(typeof(MyFeatureList)))
{
features.Add(new Feature(feature, true));
}
return features;
}
}
#endregion AddFeatures
#endregion PrivateProperties
#region PublicProperties
public IEnumerable<string> Feature1Items => features.Where(o => o != Feature2SelectedValue && o != Feature3SelectedValue && o != Feature4SelectedValue);
public IEnumerable<string> Feature2Items => features.Where(o => o != Feature1SelectedValue && o != Feature3SelectedValue && o != Feature4SelectedValue);
public IEnumerable<string> Feature3Items => features.Where(o => o != Feature1SelectedValue && o != Feature2SelectedValue && o != Feature4SelectedValue);
public IEnumerable<string> Feature4Items => features.Where(o => o != Feature1SelectedValue && o != Feature2SelectedValue && o != Feature3SelectedValue);
#endregion PublicProperties
#region Constructor
public FeatureViewModel()
{
features = AddFeatures.Select(c => c.FeatureName).ToList();
OnComboBox_ClearSelection = new BaseCommand(ClearSelection);
}
#endregion Constructor
#region Feature1SelectedValue
protected string feature1SelectedValue;
/// <summary>
/// Feature 1 selected value
/// </summary>
public string Feature1SelectedValue
{
get { return feature1SelectedValue; }
set
{
if (feature1SelectedValue != value)
{
feature1SelectedValue = value;
OnPropertyChanged();
OnPropertyChanged(nameof(Feature2Items));
OnPropertyChanged(nameof(Feature3Items));
OnPropertyChanged(nameof(Feature4Items));
}
}
}
#endregion Feature1SelectedValue
#region Feature2SelectedValue
protected string feature2SelectedValue;
/// <summary>
/// Feature 1 selected value
/// </summary>
public string Feature2SelectedValue
{
get { return feature2SelectedValue; }
set
{
if (feature2SelectedValue != value)
{
feature2SelectedValue = value;
OnPropertyChanged();
OnPropertyChanged(nameof(Feature1Items));
OnPropertyChanged(nameof(Feature3Items));
OnPropertyChanged(nameof(Feature4Items));
}
}
}
#endregion Feature2SelectedValue
#region Feature3SelectedValue
protected string feature3SelectedValue;
/// <summary>
/// Feature 1 selected value
/// </summary>
public string Feature3SelectedValue
{
get { return feature3SelectedValue; }
set
{
if (feature3SelectedValue != value)
{
feature3SelectedValue = value;
OnPropertyChanged();
OnPropertyChanged(nameof(Feature1Items));
OnPropertyChanged(nameof(Feature2Items));
OnPropertyChanged(nameof(Feature4Items));
}
}
}
#endregion Feature3SelectedValue
#region Feature4SelectedValue
protected string feature4SelectedValue;
/// <summary>
/// Feature 1 selected value
/// </summary>
public string Feature4SelectedValue
{
get { return feature4SelectedValue; }
set
{
if (feature4SelectedValue != value)
{
feature4SelectedValue = value;
OnPropertyChanged();
OnPropertyChanged(nameof(Feature1Items));
OnPropertyChanged(nameof(Feature2Items));
OnPropertyChanged(nameof(Feature3Items));
}
}
}
#endregion Feature4SelectedValue
#endregion Definitions
#region Methods
public ICommand OnComboBox_ClearSelection { get; }
public void ClearSelection(object sender)
{
ComboBox combobox = sender as ComboBox;
combobox.SelectedItem = null;
}
#endregion Methods
#region INotifyPropertyChanged Members
/// <summary>
/// Need to implement this interface in order to get data binding
/// to work properly.
/// </summary>
/// <param name="propertyName"></param>
private void NotifyPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion INotifyPropertyChanged Members
}
#region BaseCommand
public class BaseCommand : ICommand
{
private readonly Predicate<object> _canExecute;
private readonly Action<object> _method;
public event EventHandler CanExecuteChanged;
public BaseCommand(Action<object> method)
: this(method, null)
{
}
public BaseCommand(Action<object> method, Predicate<object> canExecute)
{
_method = method;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
if (_canExecute == null)
{
return true;
}
return _canExecute(parameter);
}
public void Execute(object parameter)
{
_method.Invoke(parameter);
}
#endregion BaseCommand
}
}

功能.cs:

namespace WpfApp1.Models
{
using System.ComponentModel;
public class Feature : INotifyPropertyChanged
{
public Feature()
{
}
public Feature(string featureName, bool isSelected)
{
this.featureName = featureName;
this.isSelected = isSelected;
}
private string featureName;
public string FeatureName
{
get
{
return featureName;
}
set
{
if (featureName != value)
{
featureName = value;
RaisePropertyChanged("FeatureName");
}
}
}
private bool isSelected;
public bool IsSelected
{
get
{
return isSelected;
}
set
{
if (isSelected != value)
{
isSelected = value;
RaisePropertyChanged("IsSelected");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
}
}

最新更新