Avalonia - 根据集合值更改 DataTemplate 会引发 ArgumentOutOfRangeException

问题描述 投票:0回答:1

我正在学习 Avalonia,并尝试根据自定义对象的 ObservableCollection 中的属性在两个不同的 DataTemplate 之间进行 ItemsControl 切换。

我有一个名为“Parameters”的

ObservableCollection<Parameter>
,其中“Parameter”定义如下:

public class Parameter
{
  public Parameter(string value = "") {
    if (value.ToLower() == "switch") {
      IsBool = true;
    }
  }
  
  private string _name;
  public string Name {
    get { return _name; }
    set {
      _name = value;
    }
  }

  public bool IsBool { get; set; } = false;
}

这是我的 XAML 代码,其中定义了 ItemsControl:

<ItemsControl Grid.IsSharedSizeScope="True" ItemsSource="{Binding Parameters}">
  <ItemsControl.ItemTemplate>
    <Binding Path="IsBool">
      <resources:ParameterTemplateSelector>

        <DataTemplate x:Key="true">
          <Grid Margin="20 10 ">
            <Grid.ColumnDefinitions>
              <ColumnDefinition Width="Auto" SharedSizeGroup="Label" />
              <ColumnDefinition Width="10" />
              <ColumnDefinition Width="*" MaxWidth="600" />
            </Grid.ColumnDefinitions>
            <Label Content="{ReflectionBinding Path=Name}" VerticalContentAlignment="Center"                   
                   HorizontalContentAlignment="Right" />
            <ToggleSwitch Grid.Column="2"/>
          </Grid>
        </DataTemplate>

        <DataTemplate x:Key="false">
          <Grid Margin="20 10 ">
            <Grid.ColumnDefinitions>
              <ColumnDefinition Width="Auto" SharedSizeGroup="Label" />
              <ColumnDefinition Width="10" />
              <ColumnDefinition Width="*" MaxWidth="600" />
            </Grid.ColumnDefinitions>
            <Label Content="{ReflectionBinding Path=Name}" VerticalContentAlignment="Center"
                   HorizontalContentAlignment="Right" />
            <AutoCompleteBox Name="AutoCompleteBox" Grid.Column="2"
                             HorizontalAlignment="Stretch"/>
          </Grid>
        </DataTemplate>

      </resources:ParameterTemplateSelector>
    </Binding>
  </ItemsControl.ItemTemplate>
</ItemsControl>

这是“ParameterTemplateConverter”(尽管没有它代码会给出相同的错误):

public class ParameterTemplateSelector : IDataTemplate
{
  [Content]
  public Dictionary<bool, IDataTemplate> AvailableTemplates { get; } = new Dictionary<bool, IDataTemplate>();

  public Control Build(object? param)
  {
    var key = param?.Equals(true);

    if (key == null) {
      throw new ArgumentNullException(nameof(param));
    }
    
    return AvailableTemplates[key.Value].Build(param);
  }

  public bool Match(object? data)
  {
    var key = data?.Equals(true);

    return data is bool
           && key != null
           && AvailableTemplates.ContainsKey(key.Value);
  }
}
理想情况下,这将为每个值为 true 的“IsBool”创建一个带有 ToggleSwitch 的网格,并为其余的创建一个带有 AutoCompleteBox 的网格,但尝试运行代码会出现此错误,大概是在“IsBool”绑定属性上:

错误 AVLN:0004 Avalonia:转换节点 XamlX.Ast.XamlAstObjectNode 时出现内部编译器错误: System.ArgumentOutOfRangeException:索引超出范围。必须为非负数且小于集合的大小。 (参数“索引”)

我觉得这是因为集合在运行时为空,但如果我在其他地方使用任何“参数”属性,我不会收到此错误,并且由于我无法在运行时之前填充集合,所以我不太清楚确定如何解决这个问题。

c# xaml data-binding datatemplate avaloniaui
1个回答
0
投票
您的代码主要有两处错误。

首先,

<resources:ParameterTemplateSelector>

 不应在绑定内声明。 XAML 应该如下所示:

<ItemsControl ItemsSource="{Binding Parameters}" ...> <ItemsControl.ItemTemplate> <resources:ParameterTemplateSelector> <DataTemplate x:Key="true"> ... </DataTemplate> <DataTemplate x:Key="false"> ... </DataTemplate> </resources:ParameterTemplateSelector> </ItemsControl.ItemTemplate> </ItemsControl>
其次,

ParameterTemplateSelector

的代码应该是这样的:

public class ParameterTemplateSelector : IDataTemplate { [Content] public Dictionary<string, IDataTemplate> AvailableTemplates { get; } = new Dictionary<string, IDataTemplate>(); public Control Build(object? data) { var parameter = (Parameter)data; return AvailableTemplates[parameter.IsBool.ToString().ToLower()].Build(data); } public bool Match(object? data) { return data is Parameter; } }
    
© www.soinside.com 2019 - 2024. All rights reserved.