在AvaloniaUI視窗,我想有一個TabControl,其選項卡添加和洗掉的ObservableCollection<T>。標簽的“標題”(出現在標簽條上的文本)應該設定在集合的每個專案中,這些專案可能屬于不同的型別。
為此,我定義了一個型別:
public abstract class TabViewModelBase : ViewModelBase
{
public abstract string TabHeader { get; }
}
我的收藏是這樣定義的:
public ObservableCollection<TabViewModelBase> OpenTabs { get; } = new();
在 axaml 檔案中,這是以下內容的定義TabControl:
<TabControl Items="{Binding OpenTabs}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding TabHeader}"/>
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
到目前為止,這就像一個魅力。
當我還想為每個選項卡內的視圖設定一個容器時,問題就開始了,它不應該是包含的視圖本身的一部分。我已經嘗試通過編輯上面的 xaml 并設定ContentTemplate如下:
<TabControl Items="{Binding OpenTabs}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding TabHeader}"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<Border Child="{Binding}"/>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
但是,這會導致以下錯誤:
[Binding] Error in binding to 'Avalonia.Controls.Border'.'Child': 'Could not convert 'Project.ViewModels.TestingViewModel' to 'IControl'.'
這似乎是因為ViewLocator沒有呼叫根據名稱自動將視圖模型與視圖匹配的 。我認為這是因為我定義了一個 DataTemplateinside TabControl.ContentTemplate。
是否可以指示 Avalonia 使用ViewLocatorinside TabControl.ContentTemplate,以便根據其名稱選擇視圖?
uj5u.com熱心網友回復:
<Border Child="{Binding}"/>
Border 期望實際控制元件作為子控制元件,而不是視圖模型。你需要ContentControl改用。它還可以擁有自己的資料模板或視圖定位器。
uj5u.com熱心網友回復:
我找到了解決這個問題的方法,通過定義一個IValueConverter在ViewLocator內部使用:
public class ViewModelValueConverter : IValueConverter
{
public object? Convert(
object value, Type targetType, object parameter, CultureInfo culture
)
{
if (value == null)
return null;
if (
value is ViewModelBase viewModel
&& targetType.IsAssignableFrom(typeof(IControl))
)
{
ViewLocator viewLocator = new();
return viewLocator.Build(value);
}
throw new NotSupportedException();
}
public object ConvertBack(
object value, Type targetType, object parameter, CultureInfo culture
)
{
throw new NotSupportedException();
}
}
并在 XAML 中使用它:
<Window.Resources>
<local:ViewModelValueConverter x:Key="variableView"/>
</Window.Resources>
<TabControl Items="{Binding OpenTabs}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding TabHeader}"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<Border Child="{Binding, Converter={StaticResource variableView}}"/>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
但感覺可能有一個更簡單的解決方案。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/313984.html
