PropertyGrid 去除列排序

本文介绍了一段用于 ExtJS 中 PropertyGrid 控件自定义设置源数据的方法,通过覆盖原型函数 setSource 来实现对 propStore 的更新,并移除了默认的排序信息。

只为自用方便!

 

 

Ext.grid.PropertyGrid.prototype.setSource = function(source) {
  delete this.propStore.store.sortInfo;
  this.propStore.setSource(source);
};

 

 

 

界面<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
// 动态表格生成器 class DynamicTableGenerator { /** * 构造函数 * @param {Object} config - 表格配置对象 */ constructor(config) { this.config = { searchFields: [], // 设置默认值,避免undefined错误 ...config }; } /** * 生成表格组件的JavaScript代码 * @returns {string} - 完整的表格组件JS代码 */ generateTableComponent() { const { componentId, tableName, columns = [], // 增加默认值 hasSearch = false, // 增加默认值 searchFields, accountId = '', // 增加默认值 year = new Date().getFullYear() // 增加默认值 } = this.config; // 1. 生成查询字段的data部分(统一缩进,避免生成代码杂乱) let queryData = ''; if (hasSearch && searchFields.length > 0) { queryData = `query: { ${searchFields.map(field => ` ${field.field}: ''`).join(',\n')} },`; } // 2. 生成配置(修复JSON转义,确保对象格式正确) const columnsConfig = JSON.stringify(columns, null, 6) // 缩进6格,匹配组件内data结构 .replace(/"([^"]+)":/g, '$1:') // 去掉key的双引号,转为Vue可识别的对象字面量 .replace(/\\"/g, '"'); // 处理转义引号(如label含双引号时) // 3. 生成搜索框模板(统一缩进,避免污染外层template) let searchTemplate = ''; if (hasSearch && searchFields.length > 0) { const colSpan = Math.max(2, Math.floor(24 / searchFields.length)); // 最小占2,避免布局错乱 // 用String.raw确保内部引号不被转义,同时统一缩进为4格(匹配template内部结构) searchTemplate = String.raw` <!-- 查询条件区域 --> <div class="search-container" style="margin-bottom: 20px; padding: 10px; background-color: #f5f7fa; border-radius: 4px;"> <el-row :gutter="20"> ${searchFields.map((field) => ` <el-col :span="${colSpan}"> <el-input v-model="query.${field.field}" placeholder="${field.placeholder || `请输入${field.label || ''}`}" clearable ></el-input> </el-col>`).join('\n')} </el-row> <div style="margin-top: 10px;"> <el-button @click="handleSearch" type="primary">查询</el-button> <el-button @click="resetSearch" style="margin-left: 10px;">重置</el-button> </div> </div>`; } // 4. 生成表格模板(修复属性绑定,统一缩进) const tableColumnsTemplate = columns.map(column => String.raw` <el-table-column :prop="${JSON.stringify(column.prop)}" :label="${JSON.stringify(column.label || '')}" :width="${column.width ? JSON.stringify(column.width) : '""'}" :sortable="true" :align="${JSON.stringify(column.align || 'left')}" :header-align="${JSON.stringify(column.align || 'left')}" :visible="${column.visible ?? true}" ></el-table-column>`).join(''); // 5. 构建完整组件代码(核心:彻底处理template的嵌套转义) const componentCode = String.raw`// 动态生成的表格组件 - ${componentId} import createExportMixin from './mixins/export-mixin.js'; import axios from 'axios'; // 确保导入axios // 创建mixin实例 const exportMixin1 = createExportMixin(); Vue.component('${componentId}', { mixins: [exportMixin1], data() { return { tableData: [], currentPage: 1, pageSize: 10, total: 0, // 查询条件 ${queryData} // 排序相关配置 sortField: '', sortOrder: '', // 配置信息 columns: ${columnsConfig}, // 设置对话框显示状态 columnSettingDialogVisible: false, // 账套信息 accountId: '${accountId}', year: '${year}', tableName: '${tableName || '数据表格'}' }; }, mounted() { this.fetchTableData(); }, methods: { /** * 查询数据方法 */ handleSearch() { console.log('查询按钮被点击,查询条件:', this.query); this.currentPage = 1; this.fetchTableData(); }, /** * 重置查询条件方法 */ resetSearch() { // 重置查询条件 ${hasSearch && searchFields.length > 0 ? `this.query = { ${searchFields.map(field => ` ${field.field}: ''`).join(',\n')} };` : ''} this.currentPage = 1; this.fetchTableData(); }, /** * 处理表格排序变化 */ handleSortChange({ prop, order }) { this.sortField = prop; this.sortOrder = order; this.fetchTableData(); }, /** * 获取表格数据方法 */ fetchTableData() { console.log('获取表格数据:', this.tableName); const params = { page: this.currentPage, page_size: this.pageSize, table_name: this.tableName, account_id: this.accountId, year: this.year }; // 添加查询条件 ${hasSearch && searchFields.length > 0 ? searchFields.map(field => ` if (this.query.${field.field}?.trim()) { params['${field.field}'] = this.query.${field.field}.trim(); }`).join('') : ''} // 添加排序参数 if (this.sortField && this.sortOrder) { params.order_field = this.sortField; params.order_direction = this.sortOrder === 'ascending' ? 'asc' : 'desc'; } // 发送请求 axios.get('/api/generic/query/', { params }) .then(response => { this.tableData = response.data?.data || []; this.total = response.data?.count || 0; }) .catch(error => { console.error('获取表格数据失败:', error); this.tableData = []; this.total = 0; if (this.$message) { this.$message.error('获取表格数据失败,请重试'); } }); }, /** * 处理每页条数变化 */ handleSizeChange(size) { this.pageSize = size; this.fetchTableData(); }, /** * 处理当前页码变化 */ handleCurrentChange(current) { this.currentPage = current; this.fetchTableData(); }, /** * 实现导出mixin所需的接口方法 */ getExportData() { const exportData = this.tableData.map(item => { const row = {}; ${columns.map(column => ` row['${column.label || ''}'] = item['${column.prop}'] ?? '';`).join('')} return row; }); // 设置宽 const columnWidths = [ ${columns.map(column => ` {wch: ${column.width ? Math.floor(parseInt(column.width) / 7) : 15}}`).join(',')} ]; return { data: exportData, columnWidths: columnWidths, sheetName: '${tableName || '表格'}数据' }; }, /** * 打印表格方法 */ printTable() { const printWindow = window.open('', '_blank'); if (!printWindow) { if (this.$message) { this.$message.warning('请允许弹窗以完成打印操作'); } return; } const tableHtml = this.$el?.querySelector('.el-table')?.outerHTML || '<div>无表格数据</div>'; // 内部模板字符串用转义,避免与外层冲突 const printContent = ` <!DOCTYPE html> <html> <head> <title>打印表格</title> <link rel="stylesheet" href="../../lib/element-ui.css"> <style> @media print { body { padding: 20px; } .el-table { width: 100% !important; border-collapse: collapse; } .el-table th, .el-table td { padding: 8px !important; border: 1px solid #ddd !important; } .el-table__header-wrapper th, .el-table__body-wrapper td { border: 1px solid #ddd !important; } } </style> </head> <body> ${tableHtml} <script> window.print(); setTimeout(() => window.close(), 100); </script> </body> </html> `; printWindow.document.open(); printWindow.document.write(printContent); printWindow.document.close(); }, /** * 预览表格方法 */ previewTable() { const previewWindow = window.open('', '_blank'); if (!previewWindow) { if (this.$message) { this.$message.warning('请允许弹窗以完成预览操作'); } return; }, const tableHtml = this.$el?.querySelector('.el-table')?.outerHTML || '<div>无表格数据</div>'; // 内部模板字符串用转义 const previewContent = ` <!DOCTYPE html> <html> <head> <title>预览表格</title> <link rel="stylesheet" href="../../lib/element-ui.css"> <style> body { padding: 20px; font-family: Arial, sans-serif; } .el-table { width: 100% !important; } .el-table th, .el-table td { padding: 8px !important; } .preview-controls { position: fixed; top: 10px; right: 10px; background: white; padding: 10px; box-shadow: 0 0 10px rgba(0,0,0,0.1); z-index: 9999; } </style> </head> <body> <div class="preview-controls"> <button onclick="window.print()" style="padding: 5px 10px; margin-right: 10px;">打印</button> <button onclick="window.close()" style="padding: 5px 10px;">关闭</button> </div> ${tableHtml} </body> </html> `; previewWindow.document.open(); previewWindow.document.write(previewContent); previewWindow.document.close(); }, /** * 打开设置对话框 */ openColumnSettingDialog() { this.columnSettingDialogVisible = true; }, /** * 关闭设置对话框 */ closeColumnSettingDialog() { this.columnSettingDialogVisible = false; }, /** * 切换显示状态 */ toggleColumnVisibility(prop, visible) { const column = this.columns.find(col => col.prop === prop); if (column) { column.visible = visible; } }, /** * 重置显示状态 */ resetColumnSettings() { this.columns.forEach(column => { column.visible = true; }); }, /** * 更新对齐方式 */ updateColumnAlign(prop, align) { const column = this.columns.find(col => col.prop === prop); if (column) { column.align = align; } }, /** * 获取汇总数据 */ getSummaries(param) { const { columns, data } = param; const sums = []; columns.forEach((column, index) => { if (index === 0) { sums[index] = '合计'; return; } // 只对数字类型字段进行汇总 const values = data.map(item => Number(item[column.property])); const validValues = values.filter(val => !isNaN(val)); if (validValues.length > 0) { sums[index] = validValues.reduce((prev, curr) => { const value = Number(curr); return !isNaN(value) ? prev + value : prev; }, 0).toFixed(2); } else { sums[index] = ''; } }); return sums; } }, template: ` <div class="${componentId}"> ${searchTemplate} <div class="table-container" style="overflow-x: auto; overflow-y: auto; margin-bottom: 20px; min-width: 100%; max-height: 600px;"> <el-table style="min-width: 100%; white-space: nowrap;" border stripe :data="tableData" show-summary :summary-method="getSummaries" @sort-change="handleSortChange" :sort-orders="['ascending', 'descending', null]" > ${tableColumnsTemplate} </el-table> </div> <!-- 分页组件 --> <div class="pagination-container" style="margin-top: 20px; text-align: right;"> <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage" :page-sizes="[5, 10, 20, 50]" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="total" ></el-pagination> </div> <!-- 操作按钮区域 --> <div style="margin-top: 10px;"> <el-button @click="openExportDialog" type="primary" icon="el-icon-download" style="margin-left: 10px;">导出</el-button> <el-button @click="previewTable" type="primary" icon="el-icon-view" style="margin-left: 10px;">打印预览</el-button> <el-button @click="printTable" type="primary" icon="el-icon-printer" style="margin-left: 10px;">打印</el-button> <el-button @click="openColumnSettingDialog" type="primary" icon="el-icon-s-grid" style="margin-left: 10px;">设置</el-button> </div> <!-- 设置对话框 --> <el-dialog title="设置" :visible.sync="columnSettingDialogVisible" width="400px" @close="closeColumnSettingDialog" > <div style="max-height: 300px; overflow-y: auto;"> <div v-for="column in columns" :key="column.prop" style="margin-bottom: 10px;"> <el-checkbox v-model="column.visible" @change="(val) => toggleColumnVisibility(column.prop, val)" > {{ column.label || column.prop || '未知' }} </el-checkbox> <div v-if="column.visible" style="margin-top: 5px; margin-left: 25px;"> <el-select v-model="column.align" placeholder="对齐方式" size="small" style="width: 120px;" @change="(val) => updateColumnAlign(column.prop, val)" > <el-option label="左对齐" value="left"></el-option> <el-option label="居中" value="center"></el-option> <el-option label="右对齐" value="right"></el-option> </el-select> </div> </div> </div> <div slot="footer" class="dialog-footer"> <el-button @click="resetColumnSettings">重置</el-button> <el-button @click="closeColumnSettingDialog">确定</el-button> </div> </el-dialog> </div> ` }); `; // 外层componentCode的闭合 return componentCode; } } // 导出类 export default DynamicTableGenerator;
最新发布
09-16
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值