Purpose: to make a table in which data will be displayed page by page.

Created a UserControl . I can not understand how to bind properties that are variable and calculated. For example, the PageCount property PageCount responsible for the number of pages in a table, and if the user indicates that 50 lines can be displayed on one page, then this property should be recalculated. In my code, the value of this property is not displayed at all.

Tell me how to properly bind such properties in UserControl ?


UPDATE

I tried to make a VM and podindit to its properties DependencyProperty , as indicated in this answer , but to no avail. The PageCount property is still not calculated and displayed.

VM:

 public class PagedDataGridVM : BaseVM { private int _pageCount; private int _rowsPerPage; private IList _itemsSource; public IList ItemsSource { get { return _itemsSource; } set { _itemsSource = value; OnPropertyChanged(); } } public int RowsPerPage { get { return _rowsPerPage; } set { _rowsPerPage = value; OnPropertyChanged(); } } public int PageCount { get { return (ItemsSource.Count % RowsPerPage == 0) ? ItemsSource.Count / RowsPerPage : ItemsSource.Count / RowsPerPage + 1;} } } 

PagedDataGrid.cs:

  public partial class PagedDataGrid : UserControl { public IList OnePageItems { get; set; } public PagedDataGrid() { InitializeComponent(); userControl.DataContext = new PagedDataGridVM(); } public IList ItemsSource { get { return (IList)GetValue(ItemsSourceProperty);} set { SetValue(ItemsSourceProperty, value); } } public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IList), typeof(PagedDataGrid)); public int RowsPerPage { get { return (int)GetValue(RowsPerPageProperty); } set { SetValue(RowsPerPageProperty, value); } } public static readonly DependencyProperty RowsPerPageProperty = DependencyProperty.Register("RowsPerPage", typeof(int), typeof(PagedDataGrid), new PropertyMetadata(100)); } 

PagedDataGrid.cs.xaml:

 <UserControl x:Class="Test.Controls.PagedDataGrid" x:Name="userControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:Test" xmlns:vm="clr-namespace:Test.Controls" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> <UserControl.Resources> <Style TargetType="vm:PagedDataGrid"> <Setter Property="RowsPerPage" Value="{Binding RowsPerPage}"/> </Style> </UserControl.Resources> <Grid> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <DataGrid x:Name="dataGrid" ItemsSource="{Binding ElementName=userControl, Path=ItemsSource}" > <DataGrid.Resources> <Style TargetType="vm:PagedDataGrid"> <Setter Property="ItemsSource" Value="{Binding ItemsSource}"/> </Style> </DataGrid.Resources> </DataGrid> <Grid Grid.Row="1" x:Name="grid"> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> <ColumnDefinition /> <ColumnDefinition /> <ColumnDefinition /> <ColumnDefinition /> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Button Grid.Column="0" x:Name="btnBegin" Content="Begin" /> <Button Grid.Column="1" x:Name="btnPrev" Content="Prev" /> <TextBlock Grid.Column="2" Text="1" HorizontalAlignment="Center" VerticalAlignment="Center" /> <Button Grid.Column="3" x:Name="btnNext" Content="Next" /> <Button Grid.Column="4" x:Name="btnEnd" Content="End" /> <Separator Grid.Column="5" VerticalAlignment="Stretch" HorizontalAlignment="Center"/> <Grid Grid.Column="6"> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <TextBox Grid.Column="0" Text="1" VerticalAlignment="Center"/> <TextBlock Grid.Column="1" Text="{Binding PageCount, StringFormat=of {0}}" VerticalAlignment="Center" Margin="5,0,0,0"/> </Grid> </Grid> </Grid> 

    1 answer 1

    Act on the MVVM pattern. Take out your properties in the ViewModel. PageCount can be bound as follows.

     <Label Grid.Column="7" Content="{Binding PageCount}" /> 

    don't forget to set the DataContext to view

     <Window.DataContext> <local:MyViewModel/> </Window.DataContext> 

    To view picked up properties, use MyViewModel: INotifyPropertyChanged

    https://msdn.microsoft.com/en-us/library/ms743695 (v=vs.110).aspx

    well or do so

     {Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=PageCount} 

    There is another option, you need to specify the name of the control:

     <UserControl x:Name="This"> 

    and use binding like this:

     {Binding ElementName=This, Path=PageCount} 

    Another option is to set the DataContext for the parent control.

     <Grid DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" > <Label Grid.Column="7" Content="{Binding PageCount}"/> </Grid> 
    • four
      It is better not to change the DataContext of the control itself - in some scenarios it can be changed "outside". - Pavel Mayorov
    • four
      It is better to set a DataContext for an element that is nested directly in a UserControl. - Pavel Mayorov
    • {Binding ElementName = This, Path = PageCount}, this will not work. The correct way is {Binding ElementName = This, Path = DataContext.PageCount} - Gardes
    • one
      @ user2455111 if it sets it for Label - the whole point disappears. I meant to install DataContext for any Grid. - Pavel Mayorov
    • one