开发者论坛

 找回密码
 注册 (请使用非IE浏览器)
查看: 2770|回复: 0

[求助] 如何在WPF开发中将静态Datagrid绑定到另一个类的List属性

[复制链接]

0

精华

10

贡献

37

赞扬

帖子
1
软币
102
在线时间
5 小时
注册时间
2022-10-6
发表于 2022-10-6 17:44:07 | 显示全部楼层 |阅读模式
本帖最后由 BabyShark 于 2022-10-6 17:48 编辑

最近做项目遇到一个问题,因为我对绑定和依赖属性理解不深所以不知道怎么解决。

我有一个Listbox控件和Datagrid控件。Datagrid里第一列是Checkbox,后面是Textbox,所有显示的数据源自一个Excel表格,我加载后在Datagrid里展示。Listbox里有n个项目,我们先假设有3个。
要求是,Datagrid里的数据除非直接在GUI里手动修改,不然保持不变,无论我对其他控件做什么操作。而且就算在GUI里手动修改了也不需要在数据源里更新,修改仅对当前的运行时有效,当我重启这个程序的时候显示的数据还是跟原来一样。这个Datagrid类似一个数据池以供用户选择。代表该数据结构的类如下:
[C#] 纯文本查看 复制代码
 public class ExcelDataEntry
 {
     public bool isChecked { get; set; }
     public string note { get; set; }
     public ExcelDataEntry(string note)
     {
         this.isChecked = false;
         this.note = note;
     }
 }


Listbox里的每一项都是一个viewModelObj类的实例,这个类主要含有一个displayName属性和一个List<ExcelDataEntry>属性,用于存储Datagrid里选中的数据行。该类结构如下:
[C#] 纯文本查看 复制代码
class viewModelObj : INotifyPropertyChanged
 {
     public string displayName { get; set; }
    
     private List<ExcelDataEntry> _generalNoteList;
     public List<ExcelDataEntry> generalNoteList
     {
         get { return _generalNoteList; }
         set
         {
             _generalNoteList = value;
             OnPropertyChanged("generalNoteList");
             MessageBox.Show($"generalNoteList changed from model.");
         }
     }
    
     public viewModelObj(string name)
     {
         displayName = name;
     }
    
     #region INotifyPropertyChanged Members
     public event PropertyChangedEventHandler PropertyChanged;
    
     private void OnPropertyChanged([CallerMemberName] string propertyName = "")
     {
         if (PropertyChanged != null)
         {
             PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
         }
     }
     #endregion
 }


我尝试整个开发遵循MVVM模式,其中view model代码如下:
[C#] 纯文本查看 复制代码
 class ChangeRequestViewModel
 {
         public ObservableCollection<ExcelDataEntry> generalNoteSource { get; set; } = new ObservableCollection<ExcelDataEntry>();
         public ObservableCollection<viewModelObj> viewModelSource { get; set; } = new ObservableCollection<viewModelObj>();
        
         public ChangeRequestViewModel()
         {
             List<ExcelDataEntry> dataPool = Default.GenerateDataPool("data.xlsx", 1, 4, 1, 71, 5);
             foreach (var entry in dataPool.Where(x => x.note == "GN").ToList())
             {
                 this.generalNoteSource.Add(entry);
             }
             CatDocFactory catDocFactory = new CatDocFactory();
             foreach (var entry in catDocFactory.GetAllOpenedDocs())
             {
                 this.viewModelSource.Add(new viewModelObj(entry.displayName));
             }
         }    
 }

这其中,generalNoteSource是Datagrid里的数据来源,viewModelSource是Listbox里的数据来源。
Main.cs如下:
[C#] 纯文本查看 复制代码
public partial class MainWindow : Window
 {
     Window parentWindow;
     private ChangeRequestViewModel changeRequestDataContext;
    
     public MainWindow(Window window)
     {
         InitializeComponent();
         parentWindow = window;
         parentWindow.Visibility = Visibility.Hidden;
         LoadDefaultData();
     }
    
     private void LoadDefaultData()
     {
         changeRequestDataContext = new ChangeRequestViewModel();
     }
    
     private void export_Click(object sender, RoutedEventArgs e)
     {
         List<CatDocumentInView> output = changeRequestDataContext.viewModelSource.ToList();
     }
 }


XAML结构如下:
[XML] 纯文本查看 复制代码
<Window x:Class="A350F_Change_Request.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:local="clr-namespace:A350F_Change_Request" xmlns:changeRequestVM="clr-namespace:A350F_Change_Request.ViewModels"
     mc:Ignorable="d"
     Title="MainWindow" Height="648"  Width="1104.25" MinWidth="1148" MinHeight="648" ResizeMode="NoResize" WindowStartupLocation="CenterScreen">
     <Window.DataContext>
         <changeRequestVM:ChangeRequestViewModel/>
     </Window.DataContext>
     <Window.Resources>
         <Style TargetType="{x:Type TabControl}">
             <Setter Property="TabStripPlacement" Value="Top" />
             <Setter Property="Margin" Value="0" />
             <Setter Property="Padding" Value="0"/>
         </Style>
    
         <Style TargetType="TabItem">
             <Setter Property="FontSize" Value="10"/>
             <Setter Property="BorderBrush" Value="Pink"/>
             <Setter Property="BorderThickness" Value="10"/>
             <Setter Property="Template">
                 <Setter.Value>
                     <ControlTemplate TargetType="{x:Type TabItem}">
                         <Border x:Name="tabItemBorder" Background="{TemplateBinding Background}" BorderThickness="1,1,1,0"
     BorderBrush="Black" Margin="0,0,0,0" CornerRadius="2,2,0,0" Padding="50,0,50,0">
                             <ContentPresenter ContentSource="Header" Margin="5" />
                         </Border>
                         <ControlTemplate.Triggers>
                             <Trigger Property="IsSelected" Value="True">
                                 <Setter Property="Background" Value="#fff291"/>
                                 <Setter Property="Foreground" Value="#000"/>
                             </Trigger>
    
                             <Trigger Property="IsSelected" Value="false">
                                 <Setter Property="Background" Value="#013268"/>
                                 <Setter Property="Foreground" Value="#fff"/>
                             </Trigger>
                         </ControlTemplate.Triggers>
    
                     </ControlTemplate>
                 </Setter.Value>
             </Setter>
         </Style>
    
         <Style TargetType="ListBoxItem" x:Key="ContainerStyle">
             <Style.Triggers>
                 <Trigger Property="IsSelected" Value="True" >
                     <Setter Property="Background" Value="#fff291"/>
                     <Setter Property="Foreground" Value="#000"/>
                 </Trigger>
                 <Trigger Property="IsSelected" Value="False" >
                     <Setter Property="Foreground" Value="White"/>
                     <Setter Property="Background" Value="#013268"/>
                 </Trigger>
             </Style.Triggers>
         </Style>
     </Window.Resources>
     <Grid x:Name="mainGrid" Background="#FF111F74" HorizontalAlignment="Left" Height="619" VerticalAlignment="Top" Width="1142">
         <Grid.RowDefinitions>
             <RowDefinition Height="3*"/>
             <RowDefinition Height="4*"/>
         </Grid.RowDefinitions>
         <Grid.ColumnDefinitions>
             <ColumnDefinition Width="*"/>
             <ColumnDefinition Width="3*"/>
         </Grid.ColumnDefinitions>
         <Border Grid.Column="0" Grid.RowSpan="2" Background="#FF111F74"/>
         <Border Grid.Column="1" Background="#FF111F74"/>
         <Border Grid.Column="1" Grid.Row="1" Background="#FF111F74"/>
         <ListBox x:Name="catDocListView" Grid.Column="0" Grid.RowSpan="2" Margin="16" ItemContainerStyle="{StaticResource ContainerStyle}"  ItemsSource="{Binding viewModelSource}" DisplayMemberPath="displayName"/>
    
         <StackPanel Grid.Column="1" Margin="16" Background="white" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
             <Grid>
                 <Grid.ColumnDefinitions>
                     <ColumnDefinition/>
                     <ColumnDefinition/>
                     <ColumnDefinition/>
                     <ColumnDefinition/>
                     <ColumnDefinition/>
                     <ColumnDefinition/>
                 </Grid.ColumnDefinitions>
                 <Grid.RowDefinitions>
                     <RowDefinition/>
                     <RowDefinition/>
                     <RowDefinition/>
                 </Grid.RowDefinitions>
                 <Label Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16">Material:</Label>
                 <ComboBox x:Name="materialCombo" Grid.Column="1" HorizontalAlignment="Stretch" Margin="8" ItemsSource="{Binding Path=materialSource}"  Text="{Binding ElementName=catDocListView, Path=SelectedItem.Material}"/>
                 <Label Grid.Row="2" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16">ECN:</Label>
             </Grid>
    
             <TextBox Margin="8" Height="80" TextWrapping="Wrap" AcceptsReturn="True" Text="{Binding ElementName=catDocListView, Path=SelectedItem.ECN, Mode=TwoWay}"/>
             <Button x:Name="export" Width="80" Height="20" Content="Export" HorizontalAlignment="Right" Margin="0,0,16,0" Click="export_Click"></Button>
         </StackPanel>
         <TabControl Grid.Row="1" Grid.Column="1" Margin="16">
             <TabItem Header="General Notes" FontSize="16">
                 <DataGrid x:Name="generalNoteDG" CanUserAddRows="False" AutoGenerateColumns="False" ItemsSource="{Binding generalNoteSource}">
                     <DataGrid.Columns>
                         <DataGridCheckBoxColumn Binding="{Binding isChecked}"  />
                         <DataGridTextColumn Header="Note" Binding="{Binding note}" Width="Auto"/>
                         <DataGridTextColumn Header="No" Binding="{Binding no}" Width="Auto"/>
                         <DataGridTextColumn Header="English Note" Binding="{Binding eng}" Width="Auto"/>
                         <DataGridTextColumn Header="German Note" Binding="{Binding deu}" Width="Auto"/>
                     </DataGrid.Columns>
                 </DataGrid>
             </TabItem>
         </TabControl>
     </Grid>
 </Window>


我现在的问题就是如何实现,当我选中一个Listbox项后,如何在每次选中Datagrid里的Checkbox后,代表改行的实例被存储进那个Listbox项的generalNoteList里,删除同样。

我不清楚是否我的设计有问题,我需要修改XAML的设计才能实现这个功能。
回复

使用道具 举报

Archiver|手机版|小黑屋|开发者网 ( 苏ICP备08004430号-2 )
版权所有:南京韵文教育信息咨询有限公司

GMT+8, 2024-4-25 09:18

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表