【问题标题】:MVVM with Caliburn.micro - Populating a Datagrid control with a bindable collection带有 Caliburn.micro 的 MVVM - 使用可绑定集合填充 Datagrid 控件
【发布时间】:2020-08-10 12:56:42
【问题描述】:

我正在尝试解决无法在数据网格中查看可绑定集合的死锁。这是我努力学习 MVVM 的一部分。 MVVM 框架使用 Caliburn Micro 和同一解决方案中的单独类库项目,使用 Dapper 连接到本地 SQL 数据库。 ShellView 和 ShellViewModel 的代码粘贴在下面

ShellView - XAML

<Window x:Class="WPFUI.Views.ShellView"
        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:WPFUI.Views"
        mc:Ignorable="d"
        Title="ShellView" Height="450" Width="800" Background="Red">
    <Grid>

        <StackPanel Orientation="Horizontal" Width="100" Height="50" VerticalAlignment="Top">
            <Button x:Name="LoadCHARecRatesList" Content="CHA Rec Rates"/>
        </StackPanel>
        <DataGrid ItemsSource="{Binding Path=LstCHARecModels, Mode=OneWay}" Margin="20,100,20,30" AutoGenerateColumns="True">

        </DataGrid>

    </Grid>
</Window>

ShellViewModel代码如下:

ShellViewModel

public class ShellViewModel : Conductor<object>
    {
        private BindableCollection<CHARecModel> _lstcharecmodels;

        public BindableCollection<CHARecModel> LstCHARecModels
        {
            get
            {return _lstcharecmodels;}

            set
            {
                _lstcharecmodels = value;
                NotifyOfPropertyChange(() => LstCHARecModels);
            }
        }

        public void LoadCHARecRatesList()
        {
            var data = LoadReviewRCRRatesTbl();
            _lstcharecmodels = new BindableCollection<CHARecModel>();

            foreach (var row in data)
            {
                _lstcharecmodels.Add(new CHARecModel
                {
                    TDate = row.TDate,
                    Vendor = row.Vendor,
                    Code=row.Code,
                    NameCode=row.NameCode,
                    Price = row.Price,
                    RCRStatus=row.RCRStatus,
                    NameCodeDate = row.NameCodeDate

                });


            }

        }

    }

ShellView 上的按钮连接到 LoadCHARecRatesList 方法(它位于负责数据访问的不同类库中,此方法的输出填充可绑定集合 LstCHARecModels)并且 Datagrid 绑定到可绑定集合LstCHARecModels - 可绑定集合正在通知属性更改。目的是当在 UI 上单击按钮时,它将从 SQL 数据库中获取数据并填充数据网格。我无法解决的问题是 Datagrid 保持空白。当我通过在 LoadCHARecRatesList 方法的最后一行放置一个中断来运行代码时,我注意到集合 (LstCHARecModels) 已准确填充到 ShellViewModel 中。当我将鼠标悬停在 ShellView 中以下行 <DataGrid ItemsSource="{Binding Path=LstCHARecModels, Mode=OneWay}" Margin="20,100,20,30" AutoGenerateColumns="True"> 中的 LstCHARecModels 上时,我注意到该集合已冒泡到 Datagrid 定义中(我可以看到所有元素,并且可以钻入每个元素以查看其中的数据- 我注意到它的元素数量和每个元素的内容都是准确的)。但即使在此之后,当我运行项目时,数据网格仍然完全空白

其他尝试

在定义 Datagrid 时,我还尝试了 ````x:Name="LstCHARecModels"````` 无济于事。

我正在请求有关如何让 bindablecollection 填充数据网格的帮助。从本质上讲,它相信LstCHARecModels 可以在调试模式下在数据网格的绑定中查看,但即使如此接近,数据网格也不会被填充!

【问题讨论】:

  • 编辑 尝试寻找解决方案表明,复制方法 LoadCHARecRatesList 中的代码并将其粘贴到 ShellViewModel 构造函数中会填充数据网格。但是试图通过单击按钮触发它来实现与构造函数方法相同的结果,将可绑定集合获取到 ShellView - 但它不会填充 DataGrid。越来越好奇......

标签: wpf mvvm data-binding datagrid caliburn.micro


【解决方案1】:

你应该初始化BindableCollection&lt;CHARecModel&gt;一次,然后在你的方法中添加项目:

public class ShellViewModel : Conductor<object>
{
    private BindableCollection<CHARecModel> _lstcharecmodels = new BindableCollection<CHARecModel>();
    public BindableCollection<CHARecModel> LstCHARecModels
    {
        get { return _lstcharecmodels; }
    }

    public void LoadCHARecRatesList()
    {
        var data = LoadReviewRCRRatesTbl();
        foreach (var row in data)
        {
            _lstcharecmodels.Add(new CHARecModel
            {
                TDate = row.TDate,
                Vendor = row.Vendor,
                Code = row.Code,
                NameCode = row.NameCode,
                Price = row.Price,
                RCRStatus = row.RCRStatus,
                NameCodeDate = row.NameCodeDate

            });
        }
    }
}

如果每次调用该方法时都创建一个新集合,那么使用BindableCollection&lt;T&gt; 是没有意义的。

如果您在 setter 中引发 PropertyChanged 事件,如果您设置 property 而不是支持字段,它应该仍然有效:

public void LoadCHARecRatesList()
{
    var data = LoadReviewRCRRatesTbl();
    LstCHARecModels = new BindableCollection<CHARecModel>();

    foreach (var row in data)
    {
        ...
    }
}

【讨论】:

  • 谢谢MM8。您的回答既清晰又简洁。我很想更好地理解你关于创建可绑定集合毫无意义的观点,如果我每次调用该方法时都创建它。该方法最终从多用户 SQL 中提取数据——这或多或少需要为每个方法调用创建 Bindable 集合。如果不这样做,将意味着即使在同一个会话中,用户也会面临看到陈旧数据的风险。如果我仍然错过了你的观点,请告诉我 - 或者这对你有意义。再次感谢您的时间和帮助
  • 如果你每次都创建一个新的集合,你还不如使用List&lt;T&gt;。我就是这个意思。
  • 啊好吧!我学到了一些新东西......在我的天真中,我认为使用 List 不会将它绑定到数据网格。感谢您纠正我可能不会觉得有必要重新审视的印象.....正如我的问题以及随后的 cmets 所揭示的那样,我是一个试图拿起 WPF、MVVM 和 caliburn micro 的菜鸟 - 不必添加学习曲线已显陡峭!非常感谢您的时间和帮助。非常感谢!
  • @MangéshMéhendalé:如果您的原始问题已得到解决,请记住接受并投票赞成答案,如果您有其他问题,请提出新问题:stackoverflow.com/help/someone-answers
  • @MangéshMéhendalé:你试过这个还是发生了什么?
【解决方案2】:

通过调用公共而不是私有属性来更改您的代码:

    public void LoadCHARecRatesList()
    {
        var data = LoadReviewRCRRatesTbl();
        LstCHARecModels = new BindableCollection<CHARecModel>();

        foreach (var row in data)
        {
            LstCHARecModels.Add(new CHARecModel
            {
                TDate = row.TDate,
                Vendor = row.Vendor,
                Code=row.Code,
                NameCode=row.NameCode,
                Price = row.Price,
                RCRStatus=row.RCRStatus,
                NameCodeDate = row.NameCodeDate

            });

        }
    }

另一件事,你需要指挥吗..我不知道你使用的代码,但屏幕就足够了......

【讨论】:

  • 谢谢@Frenchy。很高兴尝试您的建议。另外,关于你对导体的观察。我是 MVVM 的新手。我知道当你有不同的屏幕时使用导体。我发布的是我的代码的一部分(我一直在努力)。整个应用程序有多个屏幕——因此,我选择了指挥。知道你现在做什么,你会相信我的方法仍然错误吗?再次感谢您的帮助
  • 不,你没有用这种方法犯错,我不知道它是如何构建你的项目的..如果你试运行多屏,是的,这是一件好事..我想你已经阅读了caliburnmicro.com/documentation/composition
  • 再次感谢法国人。我实际上是在 YouTube 上关注我的学习所依据的 Vlog。同样解释了 Conductor 是多屏项目的方式。 Caliburn 的文档读起来很痛苦——或者可能只有我一个人!
猜你喜欢
  • 2013-12-17
  • 2017-10-29
  • 1970-01-01
  • 1970-01-01
  • 2013-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-16
相关资源
最近更新 更多