【问题标题】:XAML Binding Observable Collection to DataGridXAML 将 Observable 集合绑定到 DataGrid
【发布时间】:2017-09-04 04:53:19
【问题描述】:

我遇到了基于其他属性的数据绑定问题。我的组合框工作正常,但数据网格却不行。我正在尝试使用将窗口绑定到代码隐藏 DataContext="{Binding RelativeSource={RelativeSource Self}}" 所以我可以有设计时间 Intellisense,但我有点用 x:Name:"_Window" 得到它

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="&gt;&gt;" Margin="10,85,10,0" VerticalAlignment="Top" Grid.Column="1"
            Click="cmdMoveAllHired_Click" />
    <Button x:Name="cmdReturnSingleItem" Content="&gt;" Margin="10,122,10,0" VerticalAlignment="Top"
            Grid.Column="1"  Click="cmdReturnSingleItem_Click" />
    <Button x:Name="cmdMoveAllReturned" Content="&lt;&lt;" Margin="10,196,10,0" VerticalAlignment="Top"
            Grid.Column="1"  Click="cmdMoveAllReturned_Click" />
    <Button x:Name="cmdHireSingleItem" Content="&lt;" 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));
    }
}

【问题讨论】:

  • 如果你使用过 MVVM,你可能不会遇到这个问题

标签: c# xaml data-binding


【解决方案1】:

我不相信你的ListEmployeesItemsSource 会更新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。

【讨论】:

    【解决方案2】:

    我认为您的问题是如何分配窗口的 DataContext。在您的 XAML 中,添加对命名空间的引用,以便 Window 可以找到您的 SendSms 视图模型,然后在 XAML(见下文)或 Window 的代码隐藏中分配 DataContext 属性。如果您以这种方式设置 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。
    • 好的。如果您不使用 MVVM,则完全删除所有 DataContext 和 RelativeSource 使用,只需在 WIndow 后面的代码中设置 ItemSource,如下所示:。 dgEmployees.ItemSource sendSms.ListEmployees;如果您确实想使用 MVVM,请尝试我上面的方法。 SendSms 构造函数只应为您实例化的每个 Window 调用一次。无论您是否使用 MVVM 方法,我都会确保是这种情况。
    • "...添加对命名空间的引用,以便窗口可以找到您的 SendSms 视图模型..." - OP 的 SendSms 是他的 查看不是他的VM
    猜你喜欢
    • 1970-01-01
    • 2012-12-31
    • 1970-01-01
    • 1970-01-01
    • 2017-04-18
    • 1970-01-01
    • 1970-01-01
    • 2018-10-13
    相关资源
    最近更新 更多