XAML嵌套模板绑定

本文关键字:绑定 嵌套 XAML | 更新日期: 2023-09-27 18:16:13

我有一个列表视图,我绑定多个数据模板使用DataTemplateSelector。然而,我不能构建我的项目,我得到一个错误的"对象引用不设置为对象的实例"。我将问题缩小到组合框的数据绑定ItemsSource。如果我注释掉这个组合框,我的项目就会生成。据我所知,Binding关键字在运行时求值,但这是一个编译时错误。我试图通过交换到x:Bind来解决这个错误,因为它在编译时求值,但随后需要定义DataTemplate的类型。

x:DataType={x:Type templates:FilterDropdownDataTemplate}

然而,x:Type在Windows 10通用应用程序中没有定义。有什么建议吗?

这是我的XAML:
<Page.Resources>
    <DataTemplate x:Name="DateComboboxTemplate">
        <TextBlock Text="{Binding}"/>
    </DataTemplate>
    <DataTemplate x:Name="FilterDropdownDataTemplate">
        <StackPanel>
            <TextBlock Text="{Binding Value}"/>
            <ComboBox ItemsSource="{Binding DateRanges}"
                SelectionChanged="{Binding DateSelection}"
                SelectedItem="{Binding SelectedDateRange, Mode=TwoWay}"
                ItemTemplate="{StaticResource DateComboboxTemplate}">
            </ComboBox>
        </StackPanel>
    </DataTemplate>
    <config:MainFilterTemplateSelector
        x:Name="MainFilterSelector"
        FilterDropdownTemplate="{StaticResource FilterDropdownDataTemplate}"
        />
</Page.Resources>
<ListView x:Name="FilterCategories"
          Margin="0"
          Padding="0"
          BorderThickness="0"
          ItemsSource="{Binding Filters}"
          SelectedItem="{Binding SelectedFilterCategory, Mode=TwoWay}"
          IsItemClickEnabled="True"
          SelectionChanged="{x:Bind ViewModel.OpenSubFilters}"
          ItemTemplateSelector="{StaticResource MainFilterSelector}">
</ListView>

下面是相关的c#代码(我使用MVVM模式):

public class MainFilterViewDropdownListTemplate : Filter
{
    private ObservableCollection<string> _dateRanges;
    private string _selectedDateRange;
    public MainFilterViewDropdownListTemplate() : base()
    {
        _dateRanges = new ObservableCollection<string>();
    }
    public ObservableCollection<string> DateRanges
    {
        get
        {
            return _dateRanges;
        }
        set
        {
            SetProperty(ref _dateRanges, value);
            // hard coding these 4 lines for testing for now
            _dateRanges.Add("Last 7 days");
            _dateRanges.Add("Last 14 days");
            _dateRanges.Add("Last 30 days");
            _dateRanges.Add("Custom");
        }
    }
    public string SelectedDateRange
    {
        get
        {
            return _selectedDateRange;
        }
        set
        {
            SetProperty(ref _selectedDateRange, value);
        }
    }
    public IEnumerable<Filter> AllFilters { get; set; }
    public void InitializeFields(Filter filter)
    {
        Column = filter.Column;
        DisplayType = filter.DisplayType;
        ID = filter.ID;
        IsSelected = filter.IsSelected;
        ParentId = filter.ParentId;
        SelectedCount = filter.SelectedCount;
        TotalCount = filter.TotalCount;
        Value = filter.Value;
        visibility = filter.visibility;
    }
    private void DateSelection()
    {
    }
}

public class MainFilterTemplateSelector : DataTemplateSelector
{
    public DataTemplate FilterDropdownTemplate { get; set; }
    protected override DataTemplate SelectTemplateCore(object selector)
    {
        if (selector == null)
        {
            throw new ArgumentNullException("Template is null");
        }
        if (!(selector is FilterBase))
        {
            throw new ArgumentException("This list can only be populated by a class that extends Filter.");
        }
        else
        {
            var filterType = selector as Filter;
            switch (filterType.DisplayType)
            {
                case "date":
                    return FilterDropdownTemplate;
                default:
                    return base.SelectTemplateCore(selector);
            }
        }
    }
}

public class Filter : FilterBase
{
    private int _selectedCount;
    private int _totalCount;
    private Visibility _visibility;
    public IEnumerable<Filter> Children
    {
        get;
        set;
    }
    public int TotalCount
    {
        get
        {
            return _totalCount;
        }
        set
        {
            SetProperty(ref _totalCount, value);
        }
    }
    public int SelectedCount
    {
        get
        {
            return _selectedCount;
        }
        set
        {
            SetProperty(ref _selectedCount, value);
        }
    }
    public Visibility visibility
    {
        get
        {
            return _visibility;
        }
        set
        {
            SetProperty(ref _visibility, value);
        }
    }
    public void InitializeAllChildren(IEnumerable<Filter> allFilters)
    {
        foreach (Filter item in allFilters)
        {
            item.Children = allFilters.GetAllChildrenFiltersForParentID(item.ID) as IEnumerable<Filter>;
            if (item.Children == null)
            {
                item.TotalCount = 0;
            }
            else
            {
                item.TotalCount = item.Children.Count();
                item.SelectedCount = item.Children.Where(t => t.IsSelected.Value).Count();
            }
        }
        Children = allFilters.GetAllChildrenFiltersForParentID(ID);
    }
}

public class FilterBase : ViewModelBase
{
    public int ID
    {
        get
        {
            return _id;
        }
        set
        {
            SetProperty(ref _id, value);
        }
    }

    public string Value
    {
        get
        {
            return _value;
        }
        set
        {
            SetProperty(ref _value, value);
        }
    }
    public string Column
    {
        get
        {
            return _column;
        }
        set
        {
            SetProperty(ref _column, value);
        }
    }
    public int ParentId
    {
        get
        {
            return _parentId;
        }
        set
        {
            SetProperty(ref _parentId, value);
        }
    }
    public string DisplayType
    {
        get
        {
            return _displayType;
        }
        set
        {
            SetProperty(ref _displayType, value);
        }
    }
    public bool? IsSelected
    {
        get
        {
            return _isSelected;
        }
        set
        {
            SetProperty(ref _isSelected, value);
        }
    }
    private int _id;
    private string _value;
    private string _column;
    private int _parentId;
    private string _displayType;
    private bool? _isSelected;
}

和(BindableBase来自Prism。Mvvm名称空间)

public class ViewModelBase : BindableBase, IDisposable
{
    PropertyChangeActionHelper _propertyChangeActionHelper;
    protected void RegisterPropertyChangeAction(Action action, params string[] monitoredProperties)
    {
        if (_propertyChangeActionHelper == null)
        {
            _propertyChangeActionHelper = new PropertyChangeActionHelper(this);
        }
        _propertyChangeActionHelper.RegisterPropertyChangeAction(action, monitoredProperties);
    }
    #region IDisposable Support
    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (_propertyChangeActionHelper != null)
            {
                _propertyChangeActionHelper.Dispose();
                _propertyChangeActionHelper = null;
            }
        }
    }
    ~ViewModelBase()
    {
        // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
        Dispose(false);
    }
    // This code added to correctly implement the disposable pattern.
    public void Dispose()
    {
        // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    #endregion
}

XAML嵌套模板绑定

假设声明了templates名称空间,并且FilterDropdownDataTemplate是该名称空间中的类型,您应该能够使用以下语法定义DataTemplate的数据类型,而不需要x:Type:

<DataTemplate x:DataType="templates:FilterDropdownDataTemplate">