IEnumerable<T>转换成ObservableCollection<T>

本文介绍将IEnumerable<T>转换为ObservableCollection<T>的方法,包括直接遍历添加、使用静态转换方法及扩展方法,并提供了最简洁的构造函数实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

开发中,需要将IEnumerable<T>类型变量转换成ObservableCollection<T>类型变量。

一开始,尝试以下方法实现:

//错误方法:

List<int> fromList =new List<int>();  
for(int i=0;i<5;i++)
{
    fromList.Add(i);              
}
ObservableCollection<int> toList = new ObservableCollection<int>();
toList = fromList;

很显然,这种直接使用类型隐式转换的方法是不可行的,因为List<int>类与ObservableCollection<int>类并不满足类型隐式转换的前提条件。我们都知道:子类可以隐式转换为父类,那么查看List<int>类与ObservableCollection<int>类就很容易发现,两者不存在这种继承关系。

 

于是,采用下面的方式来实现: 

//正确方法:      

foreach(int i in fromList)
{
    toList.Add(i);
}

这种做法是可行的。

在有些项目中,会有人将这样的转换方法抽取成静态类的静态方法,代码如下:

//静态转换方法

public static class ConvertHelper
{
    public static ObservableCollection<T> ConvertToObservableCollection<T>(IEnumerable<T> from)
    {
         ObservableCollection<T> to = new ObservableCollection<T>();
         foreach (var f in from)
         {
             to.Add(f);
         }
         return to;
    }
}

 这时,任何需要此种转换的地方都可以按照下面的方式来调用这个转换方法:

toList = ConvertHelper.ConvertToObservableCollection(fromList);

当然,还可以将上面的静态方法改写成扩展方法,代码如下:

//转换的扩展方法形式

public static class AdvanceConvertHelper
{
    public static ObservableCollection<T> ToObservableCollection<T>(this IEnumerable<T> from)
    {
         ObservableCollection<T> to = new ObservableCollection<T>();
         foreach (var f in from)
         {
             to.Add(f);
         }
         return to;
    }
}

这时,可以按照下面的方式来调用这个转换方法:

toList = fromList.ToObservableCollection();

前面的方法本质上都是通过遍历源集合fromList元素将其加入目标集合toList来完成转换操作的

 

其实,还有一个比较简单的方法,代码如下:

//最简单的方法:

 ObservableCollection<int> toList = new ObservableCollection<int>(fromList);

此方法主要是利用了ObservableCollection<T>类的构造函数:

public ObservableCollection(IEnumerable<T> collection)

该构造函数可以接收一个IEnumerable<T>的参数,在其内部将其转换ObservableCollection<T>,如果有机会查看.Net的源码,你会发现在构造函数中其实也是通过遍历元素来完成转换造作的(万变不离其宗啊)。

 扩展阅读:

C#扩展方法 扩你所需 C# Linq扩展方法应用 C#扩展方法调用简析 扩展方法入门 C#扩展方法初探

 

 

界面<UserControl x:Class="TEST.UserControls.UC_StationInfo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:converters="clr-namespace:TEST.Converters" xmlns:local="clr-namespace:TEST.Themes" xmlns:i="http://schemas.microsoft.com/xaml/behaviors" mc:Ignorable="d" d:DesignWidth="300" d:Height="60" MouseDoubleClick="Grid_MouseLeftButtonDown"> <UserControl.Resources> <converters:CvtBool2Visibility x:Key="cvtBool2Visibility"/> </UserControl.Resources> <Grid Background="Transparent" Height="60" > <Grid.ContextMenu> <ContextMenu Style="{x:Null}"> <MenuItem Header="移除玻片" Click="DeleteGlass_Click" Margin="0,3"/> </ContextMenu> </Grid.ContextMenu> <Grid.ColumnDefinitions> <ColumnDefinition Width="40"/> <ColumnDefinition /> </Grid.ColumnDefinitions> <Grid Height="30" Width="30" Margin="5,5,5,5"> <Ellipse VerticalAlignment="Stretch" Stroke="Black" StrokeThickness="2" /> <Label HorizontalAlignment="Center" VerticalAlignment="Center" VerticalContentAlignment="Center" d:Content="10" Content="{Binding Number, RelativeSource={RelativeSource AncestorType=UserControl},UpdateSourceTrigger=PropertyChanged}" FontSize="16" FontWeight="Bold"/> </Grid> <Grid Height="50" Width="150" Grid.Column="1"> <Border BorderBrush="Black" BorderThickness="1" CornerRadius="5" Background="#CCCCCC" Width="140" /> <Border BorderBrush="Black" BorderThickness="1" CornerRadius="5" Background="#D1FFF2" Width="140" Visibility="{Binding IsLoad, RelativeSource={RelativeSource AncestorType=UserControl},UpdateSourceTrigger=PropertyChanged, Converter={StaticResource cvtBool2Visibility}}"/> <Line Stroke="Red" StrokeThickness="2" X1="50" Y1="10" X2="100" Y2="40" Visibility="{Binding IsError, RelativeSource={RelativeSource AncestorType=UserControl},UpdateSourceTrigger=PropertyChanged, Converter={StaticResource cvtBool2Visibility}}"/> <Line Stroke="Red" StrokeThickness="2" X1="100" Y1="10" X2="50" Y2="40" Visibility="{Binding IsError, RelativeSource={RelativeSource AncestorType=UserControl},UpdateSourceTrigger=PropertyChanged, Converter={StaticResource cvtBool2Visibility}}"/> <TextBlock VerticalAlignment="Top" Margin="10,3" FontSize="14" d:Text="123456789" Text="{Binding GlassId, RelativeSource={RelativeSource AncestorType=UserControl},UpdateSourceTrigger=PropertyChanged}" /> <TextBlock VerticalAlignment="Bottom" Margin="10,3" FontSize="14" d:Text="Desmin" Text="{Binding CategoryName, RelativeSource={RelativeSource AncestorType=UserControl},UpdateSourceTrigger=PropertyChanged}" /> </Grid> </Grid> </UserControl> 后台/// <summary> /// UC_StationInfo.xaml 的交互逻辑 /// </summary> public partial class UC_StationInfo : UserControl { public UC_StationInfo() { InitializeComponent(); } public event Action<int> RemoveGlassAction; // 定义 IsError 依赖属性 public static readonly DependencyProperty IsErrorProperty = DependencyProperty.Register(nameof(IsError), typeof(bool), typeof(UC_StationInfo), new PropertyMetadata(false)); public bool IsError { get => (bool)GetValue(IsErrorProperty); set => SetValue(IsErrorProperty, value); } // 定义 IsLoad 依赖属性 public static readonly DependencyProperty IsLoadProperty = DependencyProperty.Register(nameof(IsLoad), typeof(bool), typeof(UC_StationInfo), new PropertyMetadata(false)); public bool IsLoad { get => (bool)GetValue(IsLoadProperty); set => SetValue(IsLoadProperty, value); } // 定义 CategoryName(标记名) 依赖属性 public static readonly DependencyProperty CategoryNameProperty = DependencyProperty.Register(nameof(CategoryName), typeof(string), typeof(UC_StationInfo), new PropertyMetadata(string.Empty)); public string CategoryName { get => (string)GetValue(CategoryNameProperty); set => SetValue(CategoryNameProperty, value); } // 定义 Number(序号) 依赖属性 public static readonly DependencyProperty NumberProperty = DependencyProperty.Register(nameof(Number), typeof(int), typeof(UC_StationInfo), new PropertyMetadata(1)); public int Number { get => (int)GetValue(NumberProperty); set => SetValue(NumberProperty, value); } // 依赖属性定义( public static readonly DependencyProperty GlassIdProperty = DependencyProperty.Register(nameof(GlassId), typeof(string), typeof(UC_StationInfo), new PropertyMetadata(string.Empty)); public string GlassId { get => (string)GetValue(GlassIdProperty); set { SetValue(GlassIdProperty, value); IsLoad = value.Length > 5; } } // 依赖属性定义( #region 私有方法 /// <summary> /// 统一处理添加逻辑 /// </summary> private void HandleAddGlass() { if (GlassId.Length < 5) return; RemoveGlassAction?.Invoke(Number); GlassId = CategoryName = ""; } // 合并事件处理 private void DeleteGlass_Click(object sender, RoutedEventArgs e) => HandleAddGlass(); private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) => HandleAddGlass(); #endregion } 界面<UserControl x:Class="TEST.UserControls.UC_GlassInfo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:converters="clr-namespace:TEST.Converters" xmlns:local="clr-namespace:TEST.Themes" xmlns:i="http://schemas.microsoft.com/xaml/behaviors" mc:Ignorable="d" d:DesignWidth="160" d:Height="55" MouseDoubleClick="Grid_MouseLeftButtonDown"> <Grid Background="Transparent" Height="55" Visibility="{Binding IsShow ,RelativeSource={RelativeSource AncestorType=UserControl}, UpdateSourceTrigger=PropertyChanged,Converter={converters:CvtBool2Visibility UseHidden=False}}"> <Grid.ContextMenu > <ContextMenu Style="{x:Null}"> <MenuItem Header="添加玻片" Click="AddGlass_Click" Margin="0,3"/> </ContextMenu> </Grid.ContextMenu> <Grid Height="50" Width="150" Grid.Column="1"> <Border BorderBrush="Black" BorderThickness="1" CornerRadius="5" Background="#D1FFF2" Width="140" /> <TextBlock VerticalAlignment="Top" Margin="10,3" FontSize="14" d:Text="123456789" Text="{Binding GlassId, RelativeSource={RelativeSource AncestorType=UserControl},UpdateSourceTrigger=PropertyChanged}" /> <TextBlock VerticalAlignment="Bottom" Margin="10,3" FontSize="14" d:Text="Desmin" Text="{Binding CategoryName, RelativeSource={RelativeSource AncestorType=UserControl},UpdateSourceTrigger=PropertyChanged}" /> </Grid> </Grid> </UserControl>后台 public partial class UC_GlassInfo : UserControl, INotifyPropertyChanged { public UC_GlassInfo() { InitializeComponent(); // 设置数据上下文为自身(支持绑定) DataContext = this; } public event Action<KeyValuePair<string, string>> AddGlassAction; // 定义 CategoryName(标记名) 依赖属性 public static readonly DependencyProperty CategoryNameProperty = DependencyProperty.Register(nameof(CategoryName), typeof(string), typeof(UC_GlassInfo), new PropertyMetadata(string.Empty)); public string CategoryName { get => (string)GetValue(CategoryNameProperty); set => SetValue(CategoryNameProperty, value); } // 依赖属性定义( public static readonly DependencyProperty GlassIdProperty = DependencyProperty.Register(nameof(GlassId), typeof(string), typeof(UC_GlassInfo), new PropertyMetadata(string.Empty)); public string GlassId { get => (string)GetValue(GlassIdProperty); set => SetValue(GlassIdProperty, value); } // 依赖属性定义( public static readonly DependencyProperty SampleIdProperty = DependencyProperty.Register(nameof(SampleId), typeof(string), typeof(UC_GlassInfo), new PropertyMetadata(string.Empty)); public string SampleId { get => (string)GetValue(SampleIdProperty); set => SetValue(SampleIdProperty, value); } // 依赖属性定义( public static readonly DependencyProperty IsLoadProperty = DependencyProperty.Register(nameof(IsLoad), typeof(bool), typeof(UC_GlassInfo), new PropertyMetadata(false)); public bool IsLoad { get => (bool)GetValue(IsLoadProperty); set => SetValue(IsLoadProperty, value); } // 添加 IsShow 作为 CLR 属性(支持双向绑定) private bool _isShow = true; public bool IsShow { get => _isShow; set { if (_isShow != value) { _isShow = value; OnPropertyChanged(nameof(IsShow)); // 可选:自动更新可见性 //Visibility = value ? Visibility.Visible : Visibility.Collapsed; } } } // 实现 INotifyPropertyChanged public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } #region 私有方法 /// <summary> /// 统一处理添加逻辑 /// </summary> private void HandleAddGlass() { AddGlassAction?.Invoke(new KeyValuePair<string, string>(GlassId, CategoryName)); } // 合并事件处理 private void AddGlass_Click(object sender, RoutedEventArgs e) => HandleAddGlass(); private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) => HandleAddGlass(); #endregion } 使用界面 <Window x:Class="TEST.UserControls.windows.Wd_GlassInfoAdd" 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:themes="clr-namespace:TEST.Themes" xmlns:converters="clr-namespace:TEST.Converters" mc:Ignorable="d" WindowStartupLocation="CenterScreen" Style="{StaticResource BaseWindowStyle}" Title="模块手动添加玻片" Height="800" Width="680" > <Window.Resources> <Style x:Key="ProductToggleStyle" TargetType="ToggleButton"> <Setter Property="Height" Value="35"/> <Setter Property="MinWidth" Value="30"/> <Setter Property="MaxWidth" Value="150"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="BorderBrush" Value="Black"/> <Setter Property="FontSize" Value="16"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ToggleButton"> <Border x:Name="border" Background="{TemplateBinding Background}" CornerRadius="5" Margin="5" BorderThickness="1" BorderBrush="Black"> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Margin="3,0"/> </Border> <ControlTemplate.Triggers> <Trigger Property="IsChecked" Value="True"> <Setter TargetName="border" Property="Background" Value="Green"/> </Trigger> <Trigger Property="IsChecked" Value="False"> <Setter TargetName="border" Property="Background" Value="White"/> </Trigger> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="border" Property="Background" Value="{DynamicResource Accent}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <converters:Int2BoolConverter x:Key="cvtInt2Bool"/> </Window.Resources> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="230"/> <ColumnDefinition Width="225"/> <ColumnDefinition Width="220"/> </Grid.ColumnDefinitions> <Grid> <Grid Width="32" Height="32" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="10"> <Ellipse Width="30" Height="30" VerticalAlignment="Stretch" Stroke="#4c4c4c" Fill="#4c4c4c"/> <Label Padding="3" HorizontalAlignment="Center" d:Content="A" Content="{Binding ModuleName}" FontSize="20" FontWeight="Bold" Foreground="White"/> </Grid> <Border BorderThickness="2" BorderBrush="Black" CornerRadius="5" Margin="5,50,5,50" Background="White"> <ListBox Margin="-1" ItemsSource="{Binding GlassStationList}" SelectedIndex="{Binding GlassStationSelectedIndex}" Background="Transparent"> <ListBox.Style> <Style TargetType="ListBox" > <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/> <!--<Setter Property="ScrollViewer.Padding" Value="0,0,17,0"/>--> <Setter Property="ItemContainerStyle"> <Setter.Value> <Style TargetType="ListBoxItem" > <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ListBoxItem" > <Border Name="border" BorderBrush="{x:Null}" Background="{TemplateBinding Background}" BorderThickness="2" HorizontalAlignment="Left" MaxWidth="{Binding ActualWidth,RelativeSource={RelativeSource AncestorType=ScrollViewer}, Converter={StaticResource cvtValuePlus},ConverterParameter=-20}"> <ContentPresenter/> </Border> <ControlTemplate.Triggers> <Trigger Property="IsSelected" Value="True"> <Setter Property="Background" Value="#999999"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> </Setter.Value> </Setter> </Style> </ListBox.Style> </ListBox> </Border> </Grid> <Grid Grid.Column="1"> <StackPanel Orientation="Vertical" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="0,10" IsEnabled="{Binding IsCanSeltctedItem}" Width="150"> <Label Content="筛选条件:" Width="90" FontSize="18" HorizontalAlignment="Left"/> <RadioButton GroupName="Volume" Width="70" Margin="30,3" Content="全部" IsChecked="{Binding FiltrateType, Converter={StaticResource cvtInt2Bool}, ConverterParameter=0}" /> <RadioButton GroupName="Volume" Width="70" Margin="30,3" Content="标记" IsChecked="{Binding FiltrateType, Converter={StaticResource cvtInt2Bool}, ConverterParameter=1}" /> <RadioButton GroupName="Volume" Width="80" Margin="30,3" Content="病例ID" IsChecked="{Binding FiltrateType, Converter={StaticResource cvtInt2Bool}, ConverterParameter=2}" /> </StackPanel> <DataGrid Margin="5,120,5,50" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Hidden" CanUserSortColumns="False" SelectionMode="Single" ItemsSource="{Binding FiltrateInfoList, Mode=OneWay}" SelectedItem="{Binding SelectedItem}" IsEnabled="{Binding IsCanSeltctedItem}"> <DataGrid.Columns > <DataGridTextColumn Header="序号" Width="40" Binding="{Binding Sid}" /> <DataGridTextColumn d:Header="标记/病例ID" Width="100" Binding="{Binding ReagentName}"> <DataGridTextColumn.HeaderTemplate> <DataTemplate> <TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}},Path=DataContext.FiltrateName}"/> </DataTemplate> </DataGridTextColumn.HeaderTemplate> </DataGridTextColumn> <!--<DataGridCheckBoxColumn Header="选择" Width="60" IsReadOnly="False" Binding="{Binding IsChoosed}"/>--> <!--<DataGridTemplateColumn Width="50" Header="选择" SortMemberPath="IsChoosed"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <CheckBox IsChecked="{Binding Path=IsPrefrence,Mode=TwoWay}" Style="{StaticResource CheckBoxStyleBase}" Height="15" HorizontalAlignment="Center" Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}, Path=DataContext.SetPrefrenceCommand}" /> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn>--> </DataGrid.Columns> </DataGrid> </Grid> <!--<Border Grid.Column="1" Height="350" Background="Honeydew" Margin="5" BorderBrush="Black" BorderThickness="1" CornerRadius="5"> <ScrollViewer Margin="2,10" VerticalScrollBarVisibility="Auto" Background="Transparent" HorizontalScrollBarVisibility="Disabled"> <ItemsControl x:Name="itemsControl" ItemsSource="{Binding FilteredCategoryList}" > <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <WrapPanel Orientation="Horizontal" ItemWidth="NaN" HorizontalAlignment="Left" Width="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType=ScrollViewer},Converter={StaticResource cvtValuePlus}, ConverterParameter=-16}"/> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate> <ToggleButton Content="{Binding Name}" Style="{StaticResource ProductToggleStyle}" IsChecked="{Binding IsSelected, Mode=TwoWay}"/> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </ScrollViewer> </Border>--> <Grid Grid.Column="2"> <!--<Grid Margin="5,20" Height="120" VerticalAlignment="Top"> <Border BorderBrush="Black" Grid.RowSpan="2" BorderThickness="2" CornerRadius="10" Background="Black"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="30"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <TextBlock Text="预览" Margin="8,0" VerticalAlignment="Center" Foreground="White" FontSize="18"/> <Border Background="#e7e7e7" Grid.Row="1" CornerRadius="0,0,10,10"/> <Grid Grid.Row="1"> <themes:GlassPice DataContext="{Binding GlassPiece}" Width="180" Height="60" VerticalAlignment="Center" HorizontalAlignment="Center"/> </Grid> </Grid> </Border> </Grid>--> <Label Padding="3" HorizontalAlignment="Left" Content="玻片列表" FontSize="18" VerticalAlignment="Top" Margin="10"/> <Border Margin="0,50" BorderBrush="Black" BorderThickness="2" CornerRadius="5"> <ListBox Margin="0" SelectedItem="{Binding SelectedGlassInfo}" ItemsSource="{Binding FiltrateGlassInfo}" Padding="0" ScrollViewer.CanContentScroll="False"> <ListBox.Style> <Style TargetType="ListBox"> <Setter Property="ItemContainerStyle"> <Setter.Value > <Style TargetType="ListBoxItem"> <Setter Property="Margin" Value="0,-2"/> <Setter Property="Padding" Value="0"/> <Setter Property="VerticalContentAlignment" Value="Stretch"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ListBoxItem"> <Border Name="border" BorderBrush="{x:Null}" Background="{TemplateBinding Background}" BorderThickness="2" Height="{TemplateBinding Height}"> <ContentPresenter VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> </Border> <ControlTemplate.Triggers> <Trigger Property="IsSelected" Value="True"> <Setter Property="Background" Value="#999999"/> </Trigger> <Trigger Property="Visibility" Value="Collapsed"> <Setter TargetName="border" Property="Height" Value="0"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> <!-- 3. 样式触发器(放在所有Setter之后) --> <Style.Triggers> <Trigger Property="Visibility" Value="Collapsed"> <Setter Property="Height" Value="0"/> <Setter Property="Focusable" Value="False"/> </Trigger> </Style.Triggers> </Style> </Setter.Value> </Setter> </Style> </ListBox.Style> </ListBox> </Border> <StackPanel Height="40" VerticalAlignment="Bottom" Orientation="Horizontal" HorizontalAlignment="Center"> <Button Content="确定" Margin="10,0" Click="ButtonOK_Click"/> <Button Content="取消" Margin="10,0" Click="ButtonCancle_Click"/> </StackPanel> </Grid> </Grid> </Window>后台程序 public partial class Wd_GlassInfoAdd : Window { public Wd_GlassInfoAdd(int states, List<string> glsIdList) { InitializeComponent(); var model = new Wd_GlassInfoAddViewModel(states, glsIdList); model.SelectedGlassListOverEvent += Model_SelectedGlassOverEventList; DataContext = model; for (int i = 0; i < GlobalVars.GlassCnt; i++) { GlassIdList.Add(""); } } public List<string> GlassIdList { get; set; } = new List<string>(); private void ButtonCancle_Click(object sender, RoutedEventArgs e) { DialogResult = false; Close(); } private void ButtonOK_Click(object sender, RoutedEventArgs e) { DialogResult = true; Close(); } private void Model_SelectedGlassOverEventList(List<string> obj) { GlassIdList = obj; } } public class Wd_GlassInfoAddViewModel : ObservableObject { private GlassLabeInfoMode selectedItem; private ObservableCollection<UC_GlassInfo> filtrateGlassInfo = new(); private ObservableCollection<GlassLabeInfoMode> filtrateInfoList = new(); private UC_GlassInfo selectedGlassInfo; private int glassStationSelectedIndex = -1; private int filtrateType = 0; private string filtrateName = "全部"; private bool isCanSeltctedItem = true; public Wd_GlassInfoAddViewModel(int states, List<string> glsIdList) { ModuleName = ((char)('A' + (char)(states >> 12))).ToString(); ; LoadFormDB(); for (int i = 0; i < GlobalVars.GlassCnt; i++) { GlassStationList.Add(new UC_StationInfo { Number = i + 1, CategoryName = "", GlassId = "", IsError = (0x01 << i & states) > 0 }); GlassStationList[i].RemoveGlassAction += RemoveGlass; if (glsIdList[i].Length > 5 && GlassStationList[i].IsError == false)//加载已经存在的玻片 { var itemToRemove = FiltrateGlassInfo.FirstOrDefault(x => x.GlassId == (glsIdList[i])); if (itemToRemove != null) { itemToRemove.IsLoad = true; itemToRemove.IsShow = false; GlassStationList[i].GlassId = itemToRemove.GlassId; GlassStationList[i].CategoryName = itemToRemove.CategoryName; } } } } /// <summary> /// 返回玻片ID列表 /// </summary> public event Action<List<string>> SelectedGlassListOverEvent; /// <summary> /// 模块名 /// </summary> public string ModuleName { get; set; } /// <summary> /// 玻片位选择编号 /// </summary> public int GlassStationSelectedIndex { get => glassStationSelectedIndex; set { glassStationSelectedIndex = value; OnPropertyChanged(); } } ///// <summary> ///// 所有玻片信息 ///// </summary> //public ObservableCollection<GlassLabeInfoMode> GlassInfoList { get; } = new ObservableCollection<GlassLabeInfoMode>(); /// <summary> /// 10个玻片位加载玻片信息 /// </summary> public ObservableCollection<UC_StationInfo> GlassStationList { get; } = new ObservableCollection<UC_StationInfo>(); public ObservableCollection<GlassLabeInfoMode> FiltrateInfoList { get => filtrateInfoList; set { SetProperty(ref filtrateInfoList, value); } } public string FiltrateName { get => filtrateName; set { SetProperty(ref filtrateName, value); } } public bool IsCanSeltctedItem { get => isCanSeltctedItem; set { SetProperty(ref isCanSeltctedItem, value); } } public GlassLabeInfoMode SelectedItem { get => selectedItem; set { if (SetProperty(ref selectedItem, value)) { if (value == null || FiltrateName == "全部") { foreach (var item in FiltrateGlassInfo) { item.IsShow = !item.IsLoad; } } else { if (FiltrateName == "标记") { foreach (var item in FiltrateGlassInfo) { if (item.CategoryName == value.ReagentName && item.IsLoad == false) { item.IsShow = true; } else { item.IsShow = false; } } } else { foreach (var item in FiltrateGlassInfo) { if (item.SampleId == value.ReagentName && item.IsLoad == false) { item.IsShow = true; } else { item.IsShow = false; } } } } } } } public int FiltrateType { get => filtrateType; set { if (SetProperty(ref filtrateType, value)) { IsCanSeltctedItem = false; SelectedItem = null; FiltrateInfoList = new ObservableCollection<GlassLabeInfoMode>(); if (value == 1)//选择标记筛选 { FiltrateInfoList = new ObservableCollection<GlassLabeInfoMode>(); FiltrateName = "标记"; var catenameList = FiltrateGlassInfo.Where(x => x.IsLoad == false).Select(x => x.CategoryName).ToList() .Where(s => !string.IsNullOrEmpty(s)).Distinct().ToList();// 去除空字符串 ,去除重复项。 转换为列表 int i = 1; foreach (var g in catenameList) { FiltrateInfoList.Add(new GlassLabeInfoMode { Sid = i++, ReagentName = g }); } } else if (value == 2)//选择病例筛选 { FiltrateName = "病例ID"; var smpList = FiltrateGlassInfo.Where(x => x.IsLoad == false).Select(x => x.SampleId).ToList() .Where(s => !string.IsNullOrEmpty(s)).Distinct().ToList();// 去除空字符串 ,去除重复项。 转换为列表 int i = 1; foreach (var g in smpList) { FiltrateInfoList.Add(new GlassLabeInfoMode { Sid = i++, ReagentName = g }); } } else { FiltrateName = "全部"; } IsCanSeltctedItem = true; } } } /// <summary> /// 过滤玻片信息 /// </summary> public ObservableCollection<UC_GlassInfo> FiltrateGlassInfo //filtrateGlassInfo { get => filtrateGlassInfo; set { if (filtrateGlassInfo != value) { if (filtrateGlassInfo != null) { foreach (var item in filtrateGlassInfo) { item.PropertyChanged -= OnGlassItemPropertyChanged; } } SetProperty(ref filtrateGlassInfo, value); foreach (var item in filtrateGlassInfo) { item.PropertyChanged += OnGlassItemPropertyChanged; } // 创建过滤视图 FilteredGlassInfoView = CollectionViewSource.GetDefaultView(filtrateGlassInfo); FilteredGlassInfoView.Filter = FilterGlassItems; } } } private ICollectionView _filteredGlassInfoView; public ICollectionView FilteredGlassInfoView { get => _filteredGlassInfoView; private set => SetProperty(ref _filteredGlassInfoView, value); } // 监听每个项的属性变化 private void OnGlassItemPropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(UC_GlassInfo.IsShow)) { FilteredGlassInfoView?.Refresh();// 当 IsShow 变化时刷新视图 } } // 过滤逻辑 private bool FilterGlassItems(object item) { if (item is UC_GlassInfo glass) { return glass.IsShow; } return false; } public UC_GlassInfo SelectedGlassInfo { get => selectedGlassInfo; set { selectedGlassInfo = value; OnPropertyChanged(); } } /// <summary> /// 移除玻片 /// </summary> /// <param name="number"></param> private void RemoveGlass(int number) { try { var dispatcher = Application.Current?.Dispatcher; if (dispatcher == null && !Dispatcher.CurrentDispatcher.CheckAccess()) { // 后台线程且没有UI上下文 return; } (dispatcher ?? Dispatcher.CurrentDispatcher).Invoke(() => { number--; if (GlassStationList[number].GlassId.Length > 5) { var itemToRemove = FiltrateGlassInfo.FirstOrDefault(x => x.GlassId == GlassStationList[number].GlassId); if (itemToRemove != null) { itemToRemove.IsLoad = false; itemToRemove.IsShow = true; } SelectedGlassListOverEvent.Invoke(GlassStationList.Select(x => x.GlassId).ToList()); } }); } catch (Exception ex) { } } private void AddGlassToModule(KeyValuePair<string, string> gls) { try { var dispatcher = Application.Current?.Dispatcher; if (dispatcher == null && !Dispatcher.CurrentDispatcher.CheckAccess()) { // 后台线程且没有UI上下文 return; } (dispatcher ?? Dispatcher.CurrentDispatcher).Invoke(() => { for (int i = 0; i < GlassStationList.Count; i++) { if (i >= GlassStationSelectedIndex) { if (GlassStationList[i].IsError == false && GlassStationList[i].CategoryName.Length < 2) { GlassStationList[i].GlassId = gls.Key; GlassStationList[i].CategoryName = gls.Value; var itemToRemove = FiltrateGlassInfo.FirstOrDefault(x => x.GlassId == gls.Key); if (itemToRemove != null) { itemToRemove.IsLoad = true; itemToRemove.IsShow = false; } SelectedGlassListOverEvent.Invoke(GlassStationList.Select(x => x.GlassId).ToList()); break; } } } }); } catch (Exception ex) { } } private void LoadFormDB() { int i = 1; using (var context = new MyContext()) { var glassData = context.Glasses.Where(x => x.IsPrinted && !x.IsDeleted && !x.IsFinished).OrderByDescending(x => x.Id) .Select(gls => new // 投影所需字段(非完整实体) { gls.GlassId, gls.DbSample.SampleId, SampleName = gls.DbSample.Name, Issequence = gls.ColorMethodEnum == ColorMethod.顺次双染, Category1Name = gls.ReagentGroup1.ContainsCategory ? gls.ReagentGroup1.FirstAntibodyName : gls.RgCategory1 != null ? gls.RgCategory1.Name : "错误", Category2Name = gls.ReagentGroup2 == null ? "无试剂" : gls.ReagentGroup2.ContainsCategory ? gls.ReagentGroup2.FirstAntibodyName : gls.RgCategory2 != null ? gls.RgCategory2.Name : "错误", }).AsNoTracking().ToList(); // 声明不跟踪变更 // 单次查询获取所有数据 // 内存中处理复杂逻辑(避免数据库无法翻译的操作) foreach (var item in glassData) { string finalReagentName = item.Category1Name; if (item.Issequence) // 处理顺次双染逻辑 { finalReagentName += "*" + item.Category2Name; } FiltrateGlassInfo.Add(new UC_GlassInfo { CategoryName = finalReagentName, GlassId = item.GlassId, SampleId = item.SampleId }); FiltrateGlassInfo.AddGlassAction += AddGlassToModule; } } } } public class GlassLabeInfoMode : ObservableObject { private string reagentName; private int sid; private string sampleName; public string GlassID { get; set; } public string ReagentName { get { return reagentName; } set { reagentName = value; OnPropertyChanged(); } } public int Sid { get => sid; set { sid = value; OnPropertyChanged(); } } public string SampleName { get => sampleName; set { sampleName = value; OnPropertyChanged(); } } } 目前上述程序运行功能上没有问题。帮我检查一下整个程序这样写有没有问题?能否更简化一些,还有我在操作的时候感觉会有点卡顿,例如在Wd_GlassInfoAdd界面,双击SelectedGlassInfo使之上载到GlassStationList,能感觉到明显的卡顿,如何解决?或者说有没有更好的方案来实现目前的功能?把改进后的代码发一下,我要做详细对比
最新发布
08-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值