好吧,所以我已经退缩了一步,可能是在错误地称呼我正在尝试做的事情……也就是说,这就是要点:
我的目标:我正在尝试创建一个简单的可重用的DataGrid,可以在基于MVVM的时间卡系统的多个区域中实现。这将用于输入数据以及可视化已提交和批准的考勤卡。请注意,控件本身不是MVVM,因为它的目标是成为可重用的控件,所以View / ViewModel是紧密耦合的。
我的问题:
我的视图(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}" />
我的实现中的错误(两个绑定都得到了此错误):
不能在类型为'timecard_UserControls _...'的'TimeCardWeekly'属性上设置'Binding'。只能在DependencyObject的DependencyProperty上设置绑定。
我如何不绑定到依赖属性?可以肯定,它们定义正确。
非常感谢您提供的任何/所有帮助。我已经为此花了太长时间了;我必须错过一些基本问题。
编辑: BaseModel使用CallerMemberName(仅是fyi)实现INotifyPropertyChanged