XAML嵌套模板绑定

时间:2015-10-06 00:01:08

标签: c# windows xaml data-binding win-universal-app

我有一个列表视图,我将多个数据模板绑定到使用DataTemplateSelector。但是,我无法构建我的项目,我收到的错误是#34;对象引用未设置为对象的实例"。我将问题缩小到组合框的数据绑定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;
}

And(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
}

1 个答案:

答案 0 :(得分:0)

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

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