WPF组合框-更改的数据源导致ItemsSource为空



我正在Page:中对组合框进行简单绑定

XAML:

<ComboBox x:Name="Cmb_test"  Grid.Column="2" Grid.Row="2" HorizontalAlignment="Left"  ItemsSource="{Binding}" />

后面的代码:

private void Page_Loaded(object sender, RoutedEventArgs e)
{
//Binding of label works fine everytime
My_label.Content = dt.Rows[0]["Column1"];
Cmb_test.DataContext = dt.DefaultView;
Cmb_test.SelectedValuePath = dt.Columns[3].ToString();
Cmb_test.DisplayMemberPath = dt.Columns[4].ToString();
//Just a check to see whether DataTable really has changed
Console.WriteLine(dt.Rows.Count.ToString());
}

但是,每当我的DataTable">dt"发生更改时,我的组合框就不再显示项目。我知道关于这个问题,大家都问了很多问题,但我能找到的都是与运行时刷新相关的问题。在我的情况下,我关闭一个页面,并在DataTable更改时重新打开它,但结果是空的组合框。

关闭我的页面的代码,用于添加:

代码与组合框位于同一页面:

private void BtnClose_Click(object sender, RoutedEventArgs e)
{
Cmb_test.ItemsSource = null;
Cmb_test.DataContext = null;
var main_window = Application.Current.MainWindow;
var frame = (main_window as MainWindow).My_Frame;
frame.Content = null;
}

主窗口中的代码:

private void My_Frame_Navigated(object sender, NavigationEventArgs e)
{
if (My_Frame.Content == null)
{
My_Frame.RemoveBackEntry();
}
}

编辑-另一次尝试:

XAML:

<Page.Resources>
<CollectionViewSource x:Key="My_source"/>
</Page.Resources>
<ComboBox x:Name="Cmb_test" ItemsSource="{Binding Source={StaticResource My_source}}" DisplayMemberPath="Column1"/>

后面的代码:

private void Page_Loaded(object sender, RoutedEventArgs e)
{
var combo_datasource = new CollectionViewSource();
combo_datasource = (CollectionViewSource)this.FindResource("seznamVrstEvidenc");
combo_datasource.Source = Tabele.dt_Sifrant.DefaultView;
}

这里发生了什么,我如何修复组合框以每次显示It’s Items?

您没有将ComboBox绑定到任何

<ComboBox x:Name="Cmb_test" [...] ItemsSource="{Binding}" />

你应该有一些收集

<ComboBox x:Name="Cmb_test" [...] ItemsSource="{Binding MyList}" />

从代码的其余部分来看,似乎是在将ComboBox"手动绑定"到DataTable。然后,您可以通过编程方式创建一个绑定,将ComboBox ItemsSource链接到DataTable DefaultView。

不过,如果你所说的"DataTable is changed"是类似的意思,那就有问题了

dt = new DataTable();

dt = Db.GetTable();

您可能会再次遇到同样的问题,因为绑定是在两个实例之间完成的,所以当创建新的dt时,您必须将其重新绑定到ComboBox。

另一种解决问题的方法是,每次有新的DataTable时都设置ComboBox ItemsSource。

我希望我能帮上忙。

---------更新--------

根据我的评论,我将在存储DataTabledt的类上实现INotifyPropertyChanged。

public class ThatParticulareClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{  
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
// [...] all the other stuff
public void MethodThatUpdateDataTable()
{
// Update DataTable
NotifyPropertyChanged(nameof(dt));
}
}

这应该行得通。如果您对DataTable对象的更改仅来自用户(来自视图(,则应在控件处注册,该控件将DataTable公开为结束编辑事件(类似于DataGrid.RowEditEnding(。此时,您将调用NotifyPropertyChanged(nameof(dt((;(请确保此调用来自包含DataTable dt的同一类(

实施

我找到了一个解决方案。在你熟悉WPF和绑定控件之前,我必须说一件非常令人沮丧的事情。。。

我阅读了大量的文章,以了解在WPF中,您应该使用MVVM模式来正确绑定控件。然而,有很多不同的方法可以做到这一点,所以我最终选择了一种至少在这一点上我不太能理解的方法:

1.(创建模型类。在这里,您可以定义DataTable列,并将它们作为属性公开。此类需要从INotifyPropertyChanged:继承

class Test_Model : INotifyPropertyChanged
{
private string col1;
private string col2;
public string Col1
{
get
{
return col1;
}
set
{
col1 = value;
OnPropertyChanged("Col1");
}
}
public string Col2
{
get
{
return col2;
}
set
{
col2 = value;
OnPropertyChanged("Col2");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}

2.(创建Viev_Model类。在这里创建一个IList(Test_Model类型(并用DataTable填充它,我使用了LINQ,这也是一个挑战。接下来,您再次公开IList类型的属性,以便将其用作数据源:

class Test_ViewModel
{
private IList<Test_Model> _comboData;
public Test_ViewModel()
{
_comboData = dt.AsEnumerable().
Select(row => new Test_Model
{
Col1 = row.Field<string>(0),
Col2 = row.Field<string>(1)
}).ToList();
}
public IList<Test_Model> ComboData
{
get { return _comboData; }
set { _comboData = value; }
}
}

3.(在窗口或页面中,将DataContext分配给View_Model类。这是在构造函数中完成的,如下所示:

public partial class My_Page: Page
{
public My_Page()
{
InitializeComponent();
this.DataContext = new Test_ViewModel(); //assign ViewModel class
}
//...
}

4.(将组合框绑定到View_Model类:

<ComboBox x:Name="Cmb_Test" ItemsSource="{Binding Path= ComboData}" 
DisplayMemberPath="Col1" SelectedValuePath="Col1" SelectedIndex="0"/>

然后它终于奏效了。虽然我对解决方案不满意,但我必须想出更简单的方法来进行适当的绑定。我通常有很多控件要绑定&如果我对我需要的每一个DataTable都这样做,我最终会在类中得到大量的代码。

最新更新