【问题标题】:ComboBox items don't show up until the 1st column is sorted在对第一列进行排序之前,ComboBox 项目不会显示
【发布时间】:2019-12-29 19:02:41
【问题描述】:

第 2 列项目“点设置”直到第 1 列项目排序后才会显示,单击第 1 列的标题。此代码的目标是链接第 1 列和第 2 列项,然后使用第 2 列项作为搜索键。

我是 C# 和 WPF 的新手。 我厌倦了将序号放在第一列项目(1.、2. 等)的前面,因为我认为如果这些项目最初被排序会解决问题。但是,没有运气。我听说 ObservableCollection 不管理输入顺序,所以一旦我用 List 更改了它。但它也没有解决这个问题。

实际上,我不想对第一列进行排序;它们应该是固定的,根本不需要更改订单/编号。

为避免任何混淆,让我展示我的整个代码(对不起)。

MainWindow.xaml:

<Window x:Class="XY.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:XY"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="454.4">
    <Grid>
        <DataGrid ItemsSource="{Binding channels}"
            SelectedItem="{Binding SelectedRow, Mode=TwoWay}"
                  Margin="0,0,0,-0.2">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding name}"
                                    Header="Channel" Width="Auto"/>
                <DataGridTemplateColumn Width="100" Header="Point Setting">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox x:Name="piontsComboBox"
                                      ItemsSource="{Binding DataContext.points,
                                RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                                      SelectionChanged="PrintText"
                                      DisplayMemberPath="name" 
                                      SelectedValuePath="name"
                                      Margin="5"
                                      SelectedItem="{Binding DataContext.SelectedPoint,
                                RelativeSource={RelativeSource AncestorType={x:Type Window}},
                                Mode=TwoWay}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
        <TextBox x:Name="tb" Width="140" Height="30" Margin="10,250,200,30"></TextBox>
        <Button x:Name="Browse_Button" Content="Browse" Margin="169,255,129.6,0"
                    Width="75" Click="Browse_Button_Click" Height="30" VerticalAlignment="Top"/>
    </Grid>
</Window>

MainWindow.xaml.cs:

using System;
using System.Windows;
using System.Windows.Controls;

namespace XY
{
    public partial class MainWindow : Window
    {
        public GridModel gridModel { get; set; }
        public MainWindow()
        {
            InitializeComponent();
            gridModel = new GridModel();
            this.DataContext = gridModel;
        }

        private void Browse_Button_Click(object sender, RoutedEventArgs e)
        {
            WakeupClass clsWakeup = new WakeupClass();
            clsWakeup.BrowseFile += new EventHandler(gridModel.ExcelFileOpen);
            clsWakeup.Start();
        }

        void PrintText(object sender, SelectionChangedEventArgs args)
        {
            var comboBox = sender as ComboBox;
            var selectedPoint = comboBox.SelectedItem as Point;
            tb.Text = selectedPoint.name;
        }
    }

    public class WakeupClass
    {
        public event EventHandler BrowseFile;
        public void Start()
        {
            BrowseFile(this, EventArgs.Empty);
        }
    }
}

ViewModelBase.cs:

using System.ComponentModel;

namespace XY
{
    public class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string name)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }
    }
}

Point.cs:

namespace XY
{
    public class Point : ViewModelBase
    {
        private string _name;
        public string name
        {
            get { return _name; }
            set
            {
                _name = value;
                OnPropertyChanged("name");
            }
        }

        private int _code;
        public int code
        {
            get { return _code; }
            set
            {
                _code = value;
                OnPropertyChanged("code");
            }
        }
    }
}

记录.cs:

namespace XY
{
    public class Record : ViewModelBase
    {
        private string _name;
        public string name
        {
            get { return _name; }
            set
            {
                _name = value;
                OnPropertyChanged("name");
            }
        }

        private int _PointCode;
        public int PointCode
        {
            get { return _PointCode; }
            set
            {
                _PointCode = value;
                OnPropertyChanged("PointCode");
            }
        }

        private Record _selectedRow;
        public Record selectedRow
        {
            get { return _selectedRow; }
            set
            {
                _selectedRow = value;
                OnPropertyChanged("SelectedRow");
            }
        }

        private Point _selectedPoint;
        public Point SelectedPoint
        {
            get { return _selectedPoint; }
            set
            {
                _selectedPoint = value;
                _selectedRow.PointCode = _selectedPoint.code;
                OnPropertyChanged("SelectedRow");
            }
        }
    }
}

GridModel.cs:

using System.Collections.ObjectModel;
using System.Windows;

namespace XY
{
    public class GridModel : ViewModelBase
    {
        public ObservableCollection<Record> channels { get; set; }
        public ObservableCollection<Point> points { get; set; }
        public GridModel()
        {
            channels = new ObservableCollection<Record>() {
                new Record {name = "1. High"},
                new Record {name = "2. Middle"},
                new Record {name = "3. Low"}
            };
        }

        internal void ExcelFileOpen(object sender, System.EventArgs e)
        {
            points = new ObservableCollection<Point> { new Point { } };

            MessageBox.Show("Please assume that Excel data are loaded here.");
            points.Add(new Point { name = "point1", code = 1 });
            points.Add(new Point { name = "point2", code = 2 });
            points.Add(new Point { name = "point3", code = 3 });
            points.Add(new Point { name = "point4", code = 4 });
        }
    }
}

流程如下:

  1. 点击“浏览”按钮加载数据。

  2. 点击第一列“频道”对列表进行排序(目标:我想摆脱这一步)。

  3. 点击“点设置”组合框选择项目(point1、point2、...等)。

...我不知道 ObservableCollection 在这里是否合适。如果 List 或任何其他类型更好,请更改它。任何建议都会有所帮助。提前谢谢你。

【问题讨论】:

    标签: c# wpf sorting combobox datagrid


    【解决方案1】:

    像这样改变你的点ObservableCollection,因为你在UI渲染后设置集合的引用,你需要触发PropertyChanged事件来更新UI。

    private ObservableCollection<Point> _points;
    public ObservableCollection<Point> points
    {
        get { return _points; }
        set
        {
            _points = value;
            OnPropertyChanged(nameof(points));
        }     
    }
    

    另一种方法是首先初始化您的集合。

    public ObservableCollection<Point> points { get; set; } = new ObservableCollection<Point>();
    
    internal void ExcelFileOpen(object sender, System.EventArgs e)
    {
        // Do not re-initialise the collection anymore.
        //points = new ObservableCollection<Point> { new Point { } };
        points.Add(new Point { name = "point1", code = 1 });
        points.Add(new Point { name = "point2", code = 2 });
        points.Add(new Point { name = "point3", code = 3 });
    }
    

    【讨论】:

    • 两者都有效!我采用您的第二个解决方案,因为正如您所建议的,我不需要重新初始化集合。非常感谢!
    猜你喜欢
    • 2013-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-16
    • 2021-06-26
    • 1970-01-01
    • 2017-02-17
    • 1970-01-01
    相关资源
    最近更新 更多