XAML绑定可观察集合到DataGrid
我遇到了基于其他属性的数据绑定问题。我的combobox工作正常,但datagrids不是。我试图窗口结合使用 DataContext="{Binding RelativeSource={RelativeSource Self}}"
,所以我可以有时间设计的智能感知代码隐藏,但我把它用x:Name:"_Window"
XAML绑定可观察集合到DataGrid
为HRRM模型有很多实体类的了,我知道的是,属性我想要绑定太拼写正确等,但我不明白为什么DataGrid不会显示员工。我也确保数据被放置在可观察的集合中,并且我已经尝试将项源绑定到ListEmployees和SmsEmployees,并且我没有尝试过任何工作。这是我试过的最后一段代码。
<Window x:Class="GUI.Employees.Misc.SendSms"
x:Name="_Window"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Send SMS" Height="525" Width="1000" DataContext="{Binding ElementName=_Window}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="270*" />
<ColumnDefinition Width="150" />
<ColumnDefinition Width="270*" />
</Grid.ColumnDefinitions>
<ComboBox Grid.Column="0" x:Name="cmbCompany" DisplayMemberPath="Name" ItemsSource="{Binding Path=Companies, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" Margin="10,10,10,0" VerticalAlignment="Top" SelectionChanged="cmbCompany_SelectionChanged"/>
<DataGrid Grid.Column="0" x:Name="dgEmployees" Margin="10,37,10,10" IsReadOnly="True" AutoGenerateColumns="False" ItemsSource="{Binding Path=ListEmployees, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window} }">
<DataGrid.Columns>
<DataGridTextColumn Header="Company" Binding="{Binding HRCo }"/>
<DataGridTextColumn Header="First Name" Binding="{Binding FirstName}" />
<DataGridTextColumn Header="Last Name" Binding="{Binding LastName}"/>
<DataGridTextColumn Header="Craft" Binding="{Binding StdCraft}"/>
</DataGrid.Columns>
</DataGrid>
<DataGrid x:Name="dgSendSms" Margin="10,37,10,10" IsReadOnly="True" Grid.Column="2" ItemsSource="{Binding SmsEmployees, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window} }">
<DataGrid.Columns>
<DataGridTextColumn Header="Company" Binding="{Binding HRCo}"/>
<DataGridTextColumn Header="First Name" Binding="{Binding FirstName}" />
<DataGridTextColumn Header="Last Name" Binding="{Binding LastName}"/>
<DataGridTextColumn Header="Craft" Binding="{Binding StdCraft}"/>
</DataGrid.Columns>
</DataGrid>
<Button x:Name="cmdMoveAllHired" Content=">>" Margin="10,85,10,0" VerticalAlignment="Top" Grid.Column="1"
Click="cmdMoveAllHired_Click" />
<Button x:Name="cmdReturnSingleItem" Content=">" Margin="10,122,10,0" VerticalAlignment="Top"
Grid.Column="1" Click="cmdReturnSingleItem_Click" />
<Button x:Name="cmdMoveAllReturned" Content="<<" Margin="10,196,10,0" VerticalAlignment="Top"
Grid.Column="1" Click="cmdMoveAllReturned_Click" />
<Button x:Name="cmdHireSingleItem" Content="<" Margin="10,159,10,0" VerticalAlignment="Top" Grid.Column="1"
Click="cmdHireSingleItem_Click" />
<Button x:Name="cmdGenerate" Content="Generate" Grid.Column="1" Margin="10,0,10,10"
VerticalAlignment="Bottom" Click="cmdGenerate_Click" Visibility="Collapsed" />
<Button x:Name="cmdBack" Content="Back" Grid.Column="1" HorizontalAlignment="Left" Margin="10,249,0,0"
VerticalAlignment="Top" Width="130" Click="cmdBack_Click" />
<Button x:Name="cmdSendSMS" Content="Send SMS" Grid.Column="1" HorizontalAlignment="Left" Margin="10,316,0,0" VerticalAlignment="Top" Width="130" Click="cmdSendSMS_Click"/>
</Grid>
namespace GUI.Employees.Misc
{
public partial class SendSms
{
public ObservableCollection<HQCO> Companies { get; set; }
public ObservableCollection<HRRM> ListEmployees { get; set; }
private ObservableCollection<HRRM> _smsEmployees;
public ObservableCollection<HRRM> SmsEmployees {
get { return _smsEmployees; }
set { _smsEmployees = value;
}
}
public SendSms()
{
InitializeComponent();
Companies = new ObservableCollection<HQCO>(HQCO.GetActivePRCompanies());
Companies.Insert(0, new HQCO { HQCo = 0, Name = "All" });
// cmbCompany.SelectedItem = _companies.Single(x=>x.HQCo == 0);
SmsEmployees = new ObservableCollection<HRRM>();
ChangeCompany();
}
private void ChangeCompany()
{
if (((HQCO)cmbCompany.SelectedItem)?.HQCo == 0)
foreach (var co in Companies)
co.IsChecked = true;
else
foreach (var co in Companies)
if (((HQCO)cmbCompany.SelectedItem) == co)
co.IsChecked = true;
else
co.IsChecked = false;
ListEmployees = new ObservableCollection<HRRM>(Facade.GetEmployeePhoneNumbers(Companies.ToList(), false).OrderBy(x => x.SortName));
}
}
我认为你的问题是你如何分配你的窗口的DataContext。在您的XAML中,添加对命名空间的引用,以便Window可以找到您的SendSms viewmodel,然后在XAML中分配DataContext属性(请参见下文),或者在Window的代码隐藏中。如果以这种方式设置DataContext,则在绑定到SendSms视图模型时不需要使用RelativeSource,但如果要查看更改,还需要确保可观察集合的类使用实现INotifyPropertyChanged进行填充。
<Window x:Name="_Window"
xmlns:local="clr-namespace:GUI.Employees.Misc" >
<!-- set the DataContext of this Window to an instance of SendSms -->
<Window.DataContext>
<local:SendSms />
</Window.DataContext>
<DataGrid ItemsSource="{Binding ListEmployees}">
...
</DataGrid>
感谢您的回答,虽然这是导致堆栈溢出作为我假设它是创造自身的万份。这是一个非常古老的项目,我现在试图修改为使用绑定,但我可能只是考虑将其直接转换为MVVM。 – Phalanx
好的。如果你没有使用MVVM,那么完全删除所有的DataContext和RelativeSource使用,并简单地在代码后面的代码中设置ItemSource,如下所示: dgEmployees.ItemSource sendSms.ListEmployees;如果你确实想用MVVM试试我上面的方法。 SendSms构造函数应该只针对您实例化的每个窗口调用一次。无论您是否使用MVVM方法,我都会确保这种情况。 – Fredrik
_“...添加对命名空间的引用,以便Window可以找到您的SendSms viewmodel ...” - - OP的** SendSms **是他的**视图**而不是他的** VM ** – MickyD
我不相信你的ListEmployees
ItemsSource
将更新DataGrid
,因为它不是一个DependencyProperty
或者你还没有实现INotifyPropertyChanged
。它不会更新,因为您正在为该属性分配一个新实例。
而是尝试添加这对你的构造:
ListEmployees = new ObservableCollection<HRRM>();
这对您的ChangeCompany方法:
foreach (var employee in Facade.GetEmployeePhoneNumbers(Companies.ToList(), false).OrderBy(x => x.SortName))
{
ListEmployees.Add(employee);
}
以上,实际上利用ObservableCollection
,然后它应该更新UI。
如果你使用MVVM你可能不会有这个问题 – MickyD