gpt4 book ai didi

c# - XAML:为什么不能将 T 的子类添加到 T 的集合中?

转载 作者:行者123 更新时间:2023-11-30 16:50:23 24 4
gpt4 key购买 nike

编辑:如果您有兴趣,可以从 GitHub 克隆应用程序的源代码。

https://github.com/jamesqo/Sirloin

重现步骤如下:

  • git clone URL
  • 在 VS 中打开 Sirloin.Example 项目(在 src/Sirloin.Example 下)
  • 双击 Package.appxmanifest,转到打包,并生成 .pfx 文件(必需,因为它会被 gitignored,更多信息 here)
  • 在x86下运行项目,应该会命中异常

原帖

我正在为 Windows 10 开发应用程序。我遇到了一个问题,由于某种原因,我无法将 Object 的子类添加到对象集合中。这是代码:

ObservableList.cs(基本上是实现 IObservableVector 的 List 的包装器)

public sealed class ObservableList : IObservableVector<object>, IReadOnlyList<object>, INotifyPropertyChanged
{
private const string IndexerName = "Item[]";

// This is non-generic so we can expose it thru the .winmd component
private readonly List<object> list;

public event PropertyChangedEventHandler PropertyChanged;
public event VectorChangedEventHandler<object> VectorChanged;

public ObservableList()
{
this.list = new List<object>();
}

public ObservableList(IEnumerable<object> items)
{
this.list = new List<object>(items);
}

public int Count => list.Count;

int IReadOnlyCollection<object>.Count => Count;

public bool IsReadOnly => false;

public object this[int index]
{
get { return list[index]; }
set { list[index] = value; }
}

object IReadOnlyList<object>.this[int index] => this[index];

public int IndexOf(object item) => list.IndexOf(item);

public void Insert(int index, object item)
{
list.Insert(index, item);
OnPropertyChanged(nameof(Count));
OnPropertyChanged(IndexerName);
OnVectorChanged(CollectionChange.ItemInserted, (uint)index);
}

public void RemoveAt(int index)
{
list.RemoveAt(index);
OnPropertyChanged(nameof(Count));
OnPropertyChanged(IndexerName);
OnVectorChanged(CollectionChange.ItemRemoved, (uint)index);
}

public void Add(object item) =>
Insert(this.Count, item);

public void Clear()
{
list.Clear();
OnPropertyChanged(nameof(Count));
OnVectorChanged(CollectionChange.Reset, 0);
}

public bool Contains(object item) => list.Contains(item);

public void CopyTo(object[] array, int arrayIndex) =>
list.CopyTo(array, arrayIndex);

public bool Remove(object item)
{
int index = this.IndexOf(item);
if (index == -1)
return false;

this.RemoveAt(index);
OnPropertyChanged(nameof(Count));
OnVectorChanged(CollectionChange.ItemRemoved, (uint)index);
return true;
}

public IEnumerator<object> GetEnumerator() => list.GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

private void OnVectorChanged(CollectionChange change, uint index)
{
VectorChanged?.Invoke(this, new VectorChangedArgs(change, index));
}

private void OnPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}

AppView.xaml.cs 的相关部分:

public sealed partial class AppView : UserControl
{
// Some generic extensions I wrote to minimize boilerplate
public ObservableList LowerItems =>
this.GetValue<ObservableList>(LowerItemsProperty);

public static DependencyProperty LowerItemsProperty { get; } =
Dependency.Register<ObservableList, AppView>(nameof(LowerItems), LowerItemsPropertyChanged);

private static void LowerItemsPropertyChanged(AppView o, IPropertyChangedArgs<ObservableList> args)
{
var src = args.NewValue;
var dest = o.lowerView.Items;

dest.Clear();

foreach (var item in src) dest.Add(item);
}
}

MainPage.xaml(我在其中使用 AppView)

<Page
x:Class="Sirloin.Example.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="using:Sirloin">

<s:AppView>
<!--This is the part that's failing-->
<s:AppView.LowerItems>
<s:MenuItem Symbol="Contact"/>
<s:MenuItem Symbol="Contact"/>
</s:AppView.LowerItems>
</s:AppView>
</Page>

出于某种原因,当我运行该应用程序时,出现此错误:

Cannot add instance of type 'Sirloin.MenuItem' to a collection of type 'Sirloin.ObservableList'.

一看就知道ObservableList本质上是对象的集合,当然MenuItemObject的子类,没看出来为什么会这样。类型是否必须完全匹配?

不幸的是,我不能在这里使用泛型,因为我将前两个文件公开为 winmd 组件的一部分,这(奇怪地)意味着没有公共(public)泛型类型。因此,我必须将通用的所有内容都变成对象的集合。

最佳答案

您需要在构造函数 中实例化 LowerItems 集合,以便它接收任何子项。

public AppView()
{
this.InitializeComponent();

this.Loaded += (o, e) => Current = this;
LowerItems = new ObservableVector();
}

当然,这样做你还需要给 LowerItems 一个 setter(@BerinLoritsch 在 Comment 部分也指出了)。

public ObservableVector LowerItems
{
get { return this.GetValue<ObservableVector>(LowerItemsProperty); }
set { this.SetValue(LowerItemsProperty, value); }
}

为了测试,我将 ItemsSource="{Binding LowerItems, ElementName=Self}" 添加到 lowerView ListView AppView.xaml(不要忘记为 UserControl 提供一个 x:Name="Self" 以使 ElementName 绑定(bind)起作用)。

完成这些更改后,您会看到图标出现在页面的左下方。

关于c# - XAML:为什么不能将 T 的子类添加到 T 的集合中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35135877/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com