【发布时间】:2019-05-16 05:40:07
【问题描述】:
我有两个数据网格,都使用相同的 xaml(除了一个有额外的列)。一个在主窗口中,另一个在用户控件内。两者都绑定到相同项目的集合(一个当前是 ObservableCollection,另一个是数组)。项目使用 MVVM(或近似值)。
数组/主窗口工作正常 - 位置组合框加载到选定的值(它不为空),更改该值只会影响它被更改的行。
ObservableCollection/usercontrol 没有。窗口打开时不会加载位置列中的值,直到您向下滚动然后再次向上滚动。更改位置组合框会更改每个可见行(或如果关闭虚拟化,则为每行)中显示的值......包括禁用的组合框。 Bonding Level 组合框不会发生同样的情况,它的处理方式基本相同。无论呈现的数据是数组还是 ObservableCollection,都会发生这种情况。
用于生成行的类的每个实例都应该是完全独立的,没有代码隐藏来混淆值,并且在另一个文件中使用集合中完全相同的类型的极其相似的 xaml 和 c# 工作。我迷路了!
截图如下:
正确的行为(主窗口、数组)
https://i.imgur.com/SJIsTOT.png(立即加载,禁用的组合框中没有值)
https://i.imgur.com/cmjaPoR.png(单行更改)
损坏的行为(用户控件嵌入到 tabcontrol、ObservableCollection)
https://i.imgur.com/yC3iAas.png(打开的窗口不加载)
https://i.imgur.com/aQgPMCN.png(滚动后加载,包括无效值)
https://i.imgur.com/dqo39aB.png(一个组合框更改,所有行更改)
DataGrid 的 XAML 和行为不端的组合框列(无绑定错误):
<DataGrid Grid.Row ="1" Width="Auto" Height="Auto" AlternatingRowBackground="#FBE9D9" AlternationCount="2"
AutoGenerateColumns="False" GridLinesVisibility="None"
ItemsSource="{Binding Familiars}" IsSynchronizedWithCurrentItem="True">
<DataGrid.InputBindings>
<MouseBinding MouseAction="LeftDoubleClick" Command="{Binding OpenDataFamiliarWindow}" CommandParameter="{Binding Familiars/}"/>
</DataGrid.InputBindings>
<DataGrid.Resources>
<local_c:OwnedToBoolConverter x:Key="OwnedToBoolConverter"/>
<local_c:EnemyTypeToColourConverter x:Key="EnemyTypeToColour"/>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
</DataGrid.Resources>
<DataGridTemplateColumn Header="Location" Width="Auto" IsReadOnly="False">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding AvailableLocationTypes}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MinWidth="90"
SelectedItem="{Binding Info.Location, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
IsSynchronizedWithCurrentItem="True" IsEnabled="{Binding Info.Owned, Converter={StaticResource OwnedToBoolConverter}}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource DescConverter}, Mode=OneTime}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid>
UserControl 旨在绑定到的类(以及与本质上相同的数据网格的工作用途不同的唯一位):
public class ColiseumVenue : INotifyPropertyChanged
{
public BitmapImage HeaderImage { get; private set; }
public string Name { get; private set; }
public ObservableCollection<FamiliarViewModel> Familiars { get; private set; } = new ObservableCollection<FamiliarViewModel>();
private IModel m_Model;
public ColiseumVenue(IModel model, string name, IEnumerable<FamiliarViewModel> familiars)
{
Name = name;
m_Model = model;
HeaderImage = ImageLoader.LoadImage(Path.Combine(ApplicationPaths.GetViewIconDirectory(), name + ".png"));
foreach(var familiar in familiars)
{
Familiars.Add(familiar);
}
}
public ColiseumView Window { get; set; }
private BaseCommand m_openDataFamiliarWindow;
public ICommand OpenDataFamiliarWindow
{
<snip>
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
FamiliarViewModel 类的公共变量有:
public class FamiliarViewModel : INotifyPropertyChanged
{
public FamiliarInfo Info { get; set; }
public LocationTypes[] AvailableLocationTypes { get; private set; }
public OwnershipStatus[] AvailableOwnershipStatuses { get; private set; }
public BondingLevels[] AvailableBondingLevels { get; private set; }
public BookmarkState[] AvailableBookmarkStates { get; private set; }
}
FamiliarInfo 类中绑定的部分是:
public ICRUD<OwnedFamiliar> OwnedFamiliar
{
get { return m_OwnedFamiliar; }
set
{
if(m_OwnedFamiliar != value)
{
m_OwnedFamiliar = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Owned"));
}
}
}
public OwnershipStatus Owned => OwnedFamiliar != null ? OwnershipStatus.Owned : OwnershipStatus.NotOwned;
public BondingLevels? BondLevel
{
get
{
return OwnedFamiliar?.Fetch()?.BondingLevel;
}
set
{
if (value.HasValue)
{
OwnedFamiliar?.Update(f => f.BondingLevel = value.Value);
}
}
}
public LocationTypes? Location
{
get
{
return OwnedFamiliar?.Fetch()?.Location;
}
set
{
if (value.HasValue)
{
OwnedFamiliar?.Update(f => f.Location = value.Value);
}
}
}
【问题讨论】: