WPF / XAML / MVVM - UserControl - Многоразовая сетка данных - PullRequest
0 голосов
/ 13 ноября 2018

Хорошо, поэтому я загнал себя в угол и, вероятно, неправильно назвал то, что я пытаюсь сделать ... Тем не менее, вот суть:

Моя цель: я пытаюсь создать простой многоразовый DataGrid, который я могу реализовать в нескольких областях системы Time Card на основе MVVM. Это будет использоваться для ввода данных, а также для визуализации уже отправленных и утвержденных временных карт. Обратите внимание, что сам по себе элемент управления не является MVVM, так как его цель - использовать повторно используемый элемент управления, поэтому View / ViewModel тесно связан.

Мои проблемы:

  1. Привязки не выдают ошибок, но они также не работают. Я могу видеть строки, вводить новые строки, но никакие данные не передаются в мою модель представления, которая реализует мою модель.
  2. Думаю, я запутался во всей привязке этого элемента управления. DataContext есть, но, честно говоря, я совершенно не понимаю, почему он работает (и почему мне пришлось прыгать через обручи, чтобы заставить его работать). Я понимаю диссоциацию между Visual Tree и реализациями DataGridXXXColumn; но я не понимаю, почему виртуальная машина, в которой я реализую этот элемент управления, отказывается с ним согласиться (поэтому я считаю, что проблема № 1 существует).
  3. Я просмотрел сотни сообщений, пытаясь заставить это работать. Я думал, что понимаю MVVM / WPF, но тогда этот тип привязки кажется лучше, чем я. Привязки дня, указанные ниже, не подключены специально; Я пытаюсь заняться этим по одному шагу за раз, и поля со списком звучали как хорошее место для начала (упс).
  4. Если я что-то пропустил или вам нужна дополнительная информация, пожалуйста, не стесняйтесь спрашивать.

My View (UserControl)

<UserControl x:Class="TimeCard.UserControls.WeeklyGridView"
         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:TimeCard.UserControls"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="800" DataContext="{Binding}">

<UserControl.Resources>
    <ResourceDictionary>
        <CollectionViewSource x:Key="DgvItemSource" Source="{Binding TimeCardWeekly}"/>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="pack://application:,,,/Common;component/Themes/Styling.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</UserControl.Resources>

<Grid>
    <Grid.Resources>

    </Grid.Resources>
    <Grid.RowDefinitions>
        <RowDefinition Height="3" />
        <RowDefinition Height="*" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="3" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="3"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="3"/>
    </Grid.ColumnDefinitions>
    <DataGrid Grid.Column="1" Grid.Row="1" 
              AutoGenerateColumns="False" CanUserAddRows="True" CanUserDeleteRows="True" 
              HeadersVisibility="All"  AlternatingRowBackground="WhiteSmoke"
              GridLinesVisibility="Horizontal"
              CanUserResizeColumns="False" CanUserResizeRows="False" CanUserReorderColumns="False" 
              ItemsSource="{Binding Source={StaticResource DgvItemSource}, UpdateSourceTrigger=PropertyChanged}"
              SelectedItem="{Binding SelectedTimeCard, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, TargetNullValue={x:Static CollectionView.NewItemPlaceholder}}">

        <DataGrid.Columns>
            <DataGridComboBoxColumn Header="Program" Width="Auto">
                <DataGridComboBoxColumn.ElementStyle>
                    <Style TargetType="ComboBox">
                        <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=SelectedTimeCard.ProgramNumbers, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
                    </Style>
                </DataGridComboBoxColumn.ElementStyle>
            </DataGridComboBoxColumn>
            <DataGridTextColumn Header="Mon" Width="Auto" ElementStyle="{StaticResource CenterFieldText}" />
            <DataGridTextColumn Header="Tue" Width="Auto" ElementStyle="{StaticResource CenterFieldText}" />
            <DataGridTextColumn Header="Wed" Width="Auto" ElementStyle="{StaticResource CenterFieldText}" />
            <DataGridTextColumn Header="Thu" Width="Auto" ElementStyle="{StaticResource CenterFieldText}" />
            <DataGridTextColumn Header="Fri" Width="Auto" ElementStyle="{StaticResource CenterFieldText}" />
            <DataGridTextColumn Header="Sat" Width="Auto" ElementStyle="{StaticResource CenterFieldText}" />
            <DataGridTextColumn Header="Sun" Width="Auto" ElementStyle="{StaticResource CenterFieldText}" />
            <DataGridComboBoxColumn Header="Category" Width="Auto">
                <DataGridComboBoxColumn.ElementStyle>
                    <Style TargetType="ComboBox">
                        <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=SelectedTimeCard.CategoryData, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
                    </Style>
                </DataGridComboBoxColumn.ElementStyle>
            </DataGridComboBoxColumn>
            <DataGridComboBoxColumn Header="Sub Category" Width="Auto">
                <DataGridComboBoxColumn.ElementStyle>
                    <Style TargetType="ComboBox">
                        <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=SelectedTimeCard.SubcategoryData, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
                    </Style>
                </DataGridComboBoxColumn.ElementStyle>
            </DataGridComboBoxColumn>
            <DataGridTextColumn Header="Explanation" Width="*">
                <DataGridTextColumn.ElementStyle>
                    <Style TargetType="TextBlock">
                        <Setter Property="Text" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=SelectedTimeCard.Explanation, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
                    </Style>
                </DataGridTextColumn.ElementStyle>
            </DataGridTextColumn>
        </DataGrid.Columns>

    </DataGrid>
</Grid>

Моя ViewModel (определена в коде на представлении, поскольку это UserControl):

    public partial class WeeklyGridView : UserControl
{
    public WeeklyGridView()
    {
        InitializeComponent();
    }

    public ObservableCollection<WeeklyGridModel> TimeCardWeekly
    {
        get => (ObservableCollection<WeeklyGridModel>) GetValue(TimeCardWeeklyDp);
        set => SetValue(TimeCardWeeklyDp, value);
    }

    public static readonly DependencyProperty TimeCardWeeklyDp =
        DependencyProperty.Register("TimeCardWeekly", typeof(ObservableCollection<WeeklyGridModel>),
            typeof(WeeklyGridView));

    public WeeklyGridModel SelectedTimeCard
    {
        get => (WeeklyGridModel) GetValue(SelectedTimeCardDp);
        set => SetValue(SelectedTimeCardDp, value);
    }

    public static readonly DependencyProperty SelectedTimeCardDp =
        DependencyProperty.Register("SelectedTimeCard", typeof(WeeklyGridModel),
            typeof(WeeklyGridView));
}

Моя модель:

 public class WeeklyGridModel : BaseModel
{
    public WeeklyGridModel()
    {

    }

    private List<string> _programNumbers;

    public List<string> ProgramNumbers
    {
        get => Helpers.DummyData.ProgramData;
        set { _programNumbers = value; NotifyPropertyChanged(); }
    }

    private List<string> _categoryData;

    public List<string> CategoryData
    {
        get => Helpers.DummyData.CategoryData;
        set { _categoryData = value; NotifyPropertyChanged(); }
    }

    private List<string> _subcategoryData;

    public List<string> SubcategoryData
    {
        get => Helpers.DummyData.SubcategoryData;
        set { _subcategoryData = value; NotifyPropertyChanged(); }
    }

    private double _monday;

    public double Monday
    {
        get => _monday;
        set { _monday = value; NotifyPropertyChanged(); }
    }

    private double _tuesday;

    public double Tuesday
    {
        get => _tuesday;
        set { _tuesday = value; NotifyPropertyChanged(); }
    }

    private double _wednesday;

    public double Wednesday
    {
        get => _wednesday;
        set { _wednesday = value; NotifyPropertyChanged(); }
    }

    private double _thursday;

    public double Thursday
    {
        get => _thursday;
        set { _thursday = value; NotifyPropertyChanged(); }
    }

    private double _friday;

    public double Friday
    {
        get => _friday;
        set { _friday = value; NotifyPropertyChanged(); }
    }

    private double _saturday;

    public double Saturday
    {
        get => _saturday;
        set { _saturday = value; NotifyPropertyChanged(); }
    }

    private double _sunday;

    public double Sunday
    {
        get => _sunday;
        set { _sunday = value; NotifyPropertyChanged(); }
    }

    private string _explanation;

    public string Explanation
    {
        get => _explanation;
        set { _explanation = value; NotifyPropertyChanged(); }
    }
}

Ожидаемая реализация:

<userControlsInternal:WeeklyGridView 
    TimeCardWeekly="{Binding TimeCardWeekly, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
    SelectedTimeCard="{Binding SelectedTimeCard, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

Ошибка в моей реализации (я получаю это для обеих попыток привязки):

Невозможно установить привязку в свойстве TimeCardWeekly типа timecard_UserControls _... Привязка может быть установлена ​​только для свойства DependencyProperty объекта DependencyObject.

Как я не привязан к свойству зависимости? Уверен, они определены правильно.

Любая / вся ваша помощь очень ценится. Я слишком долго этим занимался; Мне должно быть не хватает какой-то фундаментальной проблемы.

Редактировать: BaseModel реализует INotifyPropertyChanged с использованием CallerMemberName (просто к вашему сведению)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...