C# 在MVVM的ViewModel中存储网格行数

C# 在MVVM的ViewModel中存储网格行数,c#,wpf,mvvm,telerik-grid,C#,Wpf,Mvvm,Telerik Grid,我正在为WPF应用程序实现MVVM。 ViewModels的创建如下所示: ViewModel:所有ViewModels都从中覆盖的基类 MainTemplateViewModel:“母版页”ViewModel,其中包含ViewModel属性Current,该属性包含要显示的ViewModel CustomerOverviewViewModel:可以放置在MainTemplateViewModel.Current中的视图示例 CustomerGridViewModel包含Telerik Gr

我正在为WPF应用程序实现MVVM。 ViewModels的创建如下所示:

  • ViewModel:所有ViewModels都从中覆盖的基类
  • MainTemplateViewModel:“母版页”ViewModel,其中包含ViewModel属性
    Current
    ,该属性包含要显示的ViewModel
  • CustomerOverviewViewModel:可以放置在
    MainTemplateViewModel.Current中的视图示例
CustomerGridViewModel包含Telerik GridView。我想显示MainTemplateViewModel标题中的项目数。
GridView.Items.Count
属性实现了
INotifyPropertyChanged
,因此我想将此属性绑定到
ViewModel.RowCount
(因为CustomerGridViewModel不知道它是MainTemplateViewModel的一部分,所以不能直接绑定到TextBlock)。我可以依次使用
ViewModel.NumberOfRecords
在标题中显示金额

如何将Count属性绑定到ViewModel中的属性

编辑

我将更详细地描述这个问题:

网格中显示的对象列表是来自ViewModel的绑定:

<telerik:RadGridView x:Name="CustomerGrid" ItemsSource="{Binding CustomerViewModels}">    
</telerik:RadGridView>
MainTemplateViewModel.cs

public class ViewModel : INotifyPropertyChanged
{
    private int numberOfRecords;

    public int NumberOfRecords
    {
        get { return numberOfRecords; }
        set { numberOfRecords = value; OnPropertyChanged(); }
    }
}
public class MainTemplateViewModel : ViewModel
{
    private ViewModel current = new MainOverviewViewModel();

    public ViewModel Current
    {
        get { return current; }
        set
        {
            if (current != value)
            {
                current = value; OnPropertyChanged();
            }
        }
    }
}
public partial class CustomerOverview : UserControl
{
    public CustomerOverview()
    {
        InitializeComponent();

        this.CustomerGrid.Items.CollectionChanged += ItemsCollectionChanged;
        this.CustomerGrid.Loaded += CustomerGrid_Loaded;
    }

    void CustomerGrid_Loaded(object sender, RoutedEventArgs e)
    {
        /* METHOD 1 PROBLEM: the field to bind to in the MainTemplate is out of scope and accessing a view is not MVVM */
        var binding = new Binding();
        binding.Path = new PropertyPath("Items.Count");
        binding.Source = CustomerGrid;
        ((MainWindow)this.ParentOfType<MainWindow>()).NumberOfRecords.SetBinding(TextBlock.TextProperty, binding);
    }


    void ItemsCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        /* METHOD 2 PROBLEM: codebehind code should be in viewmodel */
        ((CustomerOverviewViewModel)this.DataContext).NumberOfRecords = CustomerGrid.Items.Count;
    }
}
CustomerOverview.xaml.cs

public class ViewModel : INotifyPropertyChanged
{
    private int numberOfRecords;

    public int NumberOfRecords
    {
        get { return numberOfRecords; }
        set { numberOfRecords = value; OnPropertyChanged(); }
    }
}
public class MainTemplateViewModel : ViewModel
{
    private ViewModel current = new MainOverviewViewModel();

    public ViewModel Current
    {
        get { return current; }
        set
        {
            if (current != value)
            {
                current = value; OnPropertyChanged();
            }
        }
    }
}
public partial class CustomerOverview : UserControl
{
    public CustomerOverview()
    {
        InitializeComponent();

        this.CustomerGrid.Items.CollectionChanged += ItemsCollectionChanged;
        this.CustomerGrid.Loaded += CustomerGrid_Loaded;
    }

    void CustomerGrid_Loaded(object sender, RoutedEventArgs e)
    {
        /* METHOD 1 PROBLEM: the field to bind to in the MainTemplate is out of scope and accessing a view is not MVVM */
        var binding = new Binding();
        binding.Path = new PropertyPath("Items.Count");
        binding.Source = CustomerGrid;
        ((MainWindow)this.ParentOfType<MainWindow>()).NumberOfRecords.SetBinding(TextBlock.TextProperty, binding);
    }


    void ItemsCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        /* METHOD 2 PROBLEM: codebehind code should be in viewmodel */
        ((CustomerOverviewViewModel)this.DataContext).NumberOfRecords = CustomerGrid.Items.Count;
    }
}
公共部分类CustomerOverview:UserControl
{
公共CustomerOverview()
{
初始化组件();
this.CustomerGrid.Items.CollectionChanged+=ItemsCollectionChanged;
this.CustomerGrid.Loaded+=CustomerGrid\u Loaded;
}
已加载无效CustomerGrid_(对象发送方,路由目标)
{
/*方法1问题:MainTemplate中要绑定到的字段超出范围,访问视图不是MVVM*/
var binding=新绑定();
binding.Path=newPropertyPath(“Items.Count”);
binding.Source=CustomerGrid;
((主窗口)this.ParentOfType()).NumberOfRecords.SetBinding(TextBlock.TextProperty,binding);
}
void ItemsCollectionChanged(对象发送方,System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
/*方法2问题:代码隐藏代码应该在viewmodel中*/
((CustomerOverviewViewModel)this.DataContext).NumberOfRecords=CustomerGrid.Items.Count;
}
}

不要在
用户控件中加载数据,只需在其中声明相关类型的
DependencyProperty
。然后,您可以在主视图模型中加载数据,并从
UserControl
简单地将数据绑定到它。您可以执行以下简单示例:

CustomerOverview.xaml.cs
中:

public static DependencyProperty ItemsProperty = DependencyProperty.Register("Items", 
    typeof(ObservableCollection<YourDataType>), typeof(CustomerOverview), 
    new PropertyMetadata(null));

main window.xaml
(或任何相关视图)中:


如果我没弄错的话,你想让你的主人展示孩子的细节

您的主人应该能够通过您当前的财产了解您的孩子。 如果正确使用MVVM,则绑定到网格的数据来自子ViewModel

在这种情况下,您的子视图模型中已经有itemscount

在这之后,你可以对你的主人说

 <Label Content="{Binding Current.NumberOfRows}"></Label>


据介绍,您可以将源代码封装在QueryableCollectionView中,Telerik网格有两个属性

可见计数

TelerikGrid.Items.Count
总数

TelerikGrid.Items.TotalItemCount

如果这有帮助的话

这是完全正确的,但问题是获取Current.NumberOfRows属性中的可见行数。通过过滤Telerik网格(这会更改GridView.Items.Count属性),可以更改内存中可见行的数量。我已经对原来的帖子做了编辑,详细解释了这一点。谢谢你的回答!我确实看到了两个问题:首先,将有多个网格,因此我希望有逻辑来填充各个viewmodel上的网格(而不是父视图中的所有网格)。第二个问题是网格项在内存中被过滤,唯一正确的计数是GridView.items.count属性。我已经在原始帖子的编辑中解释了这一点。然后让您的
dependencProperty
UserControl
中公开
Count
值,并从主视图将数据绑定到它。