13

我在 XAML 设计器中绑定了 aGridView属性ICollectionView未知,因为其中的实体CollectionView已转换为类型Object并且无法访问实体属性,它运行良好,没有错误,但设计器将其显示为错误,如果我绑定到集合我可以正常访问属性

示例实体是Person具有string Name属性的我将它们放置在一个中ObservableCollection<Person>并从中获取视图并将其绑定到GridView.ItemsSource现在当我尝试设置列标题DataMemberBinding.FirstName属性时设计器将其显示为错误

无法解析对象类型的数据上下文中的属性“FirstName”

是错误还是 Resharper 对我耍花招

示例代码:

public class Person 
{
    public string FirstName{
       get { return _firstName; }
       set { SetPropertyValue("FirstName", ref _firstName, value); }
    }
}
public class DataService 
{
    public IDataSource DataContext { get; set; }
    public ICollectionView PersonCollection{ get; set; }

    public DataService()
    {
        DataContext = new DataSource();
        //QueryableCollectionView is from Telerik 
        //but if i use any other CollectionView same thing
        //DataContext Persons is an ObservableCollection<Person> Persons
        PersonCollection = new QueryableCollectionView(DataContext.Persons);
    }
}

<telerik:RadGridView x:Name="ParentGrid" 
    ItemsSource="{Binding DataService.PersonCollection}"
    AutoGenerateColumns="False">
    <telerik:RadGridView.Columns >
        <telerik:GridViewDataColumn Header="{lex:Loc Key=FirstName}"  
            DataMemberBinding="{Binding FirstName}"/>
    </telerik:RadGridView.Columns>
</telerik:RadGridView>

在此处输入图像描述

4

3 回答 3

8

Resharper 在 XAML 视图中给你的警告是因为控件的设计时视图不知道它的数据上下文是什么类型。您可以使用 ad:DesignInstance 来帮助您进行绑定。

添加以下内容(适当地替换程序集/命名空间/绑定目标名称)

<UserControl x:Class="MyNamespace.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup‐compatibility/2006"
mc:Ignorable="d"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:lcl="clr‐namespace:MyAssembly"
d:DataContext="{d:DesignInstance Type=lcl:ViewModel}">
于 2014-06-29T18:22:04.170 回答
1

您的实体尚未转换为对象,这是因为接口ICollectionView不是通用集合,因此 ReSharper 无法知道它包含Person.

您可以创建一个通用版本ICollectionView并将其用于您的PersonCollection财产,如本文所示https://benoitpatra.com/2014/10/12/a-generic-version-of-icollectionview-used-in-a-mvvm-可搜索列表/

首先是一些接口:

public interface ICollectionView<T> : IEnumerable<T>, ICollectionView
{
}

public interface IEditableCollectionView<T> : IEditableCollectionView
{
}

实施:

public class GenericCollectionView<T> : ICollectionView<T>, IEditableCollectionView<T>
{
    readonly ListCollectionView collectionView;

    public CultureInfo Culture
    {
        get => collectionView.Culture;
        set => collectionView.Culture = value;
    }

    public IEnumerable SourceCollection => collectionView.SourceCollection;

    public Predicate<object> Filter
    {
        get => collectionView.Filter;
        set => collectionView.Filter = value;
    }

    public bool CanFilter => collectionView.CanFilter;

    public SortDescriptionCollection SortDescriptions => collectionView.SortDescriptions;

    public bool CanSort => collectionView.CanSort;

    public bool CanGroup => collectionView.CanGroup;

    public ObservableCollection<GroupDescription> GroupDescriptions => collectionView.GroupDescriptions;

    public ReadOnlyObservableCollection<object> Groups => collectionView.Groups;

    public bool IsEmpty => collectionView.IsEmpty;

    public object CurrentItem => collectionView.CurrentItem;

    public int CurrentPosition => collectionView.CurrentPosition;

    public bool IsCurrentAfterLast => collectionView.IsCurrentAfterLast;

    public bool IsCurrentBeforeFirst => collectionView.IsCurrentBeforeFirst;

    public NewItemPlaceholderPosition NewItemPlaceholderPosition
    {
        get => collectionView.NewItemPlaceholderPosition;
        set => collectionView.NewItemPlaceholderPosition = value;
    }

    public bool CanAddNew => collectionView.CanAddNew;

    public bool IsAddingNew => collectionView.IsAddingNew;

    public object CurrentAddItem => collectionView.CurrentAddItem;

    public bool CanRemove => collectionView.CanRemove;

    public bool CanCancelEdit => collectionView.CanCancelEdit;

    public bool IsEditingItem => collectionView.IsEditingItem;

    public object CurrentEditItem => collectionView.CurrentEditItem;

    public event NotifyCollectionChangedEventHandler CollectionChanged
    {
        add => ((ICollectionView) collectionView).CollectionChanged += value;
        remove => ((ICollectionView) collectionView).CollectionChanged -= value;
    }

    public event CurrentChangingEventHandler CurrentChanging
    {
        add => ((ICollectionView) collectionView).CurrentChanging += value;
        remove => ((ICollectionView) collectionView).CurrentChanging -= value;
    }

    public event EventHandler CurrentChanged
    {
        add => ((ICollectionView) collectionView).CurrentChanged += value;
        remove => ((ICollectionView) collectionView).CurrentChanged -= value;
    }

    public GenericCollectionView([NotNull] ListCollectionView collectionView)
    {
        this.collectionView = collectionView ?? throw new ArgumentNullException(nameof(collectionView));
    }

    public IEnumerator<T> GetEnumerator()
    {
        return (IEnumerator<T>) ((ICollectionView) collectionView).GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return ((ICollectionView) collectionView).GetEnumerator();
    }

    public bool Contains(object item)
    {
        return collectionView.Contains(item);
    }

    public void Refresh()
    {
        collectionView.Refresh();
    }

    public IDisposable DeferRefresh()
    {
        return collectionView.DeferRefresh();
    }

    public bool MoveCurrentToFirst()
    {
        return collectionView.MoveCurrentToFirst();
    }

    public bool MoveCurrentToLast()
    {
        return collectionView.MoveCurrentToLast();
    }

    public bool MoveCurrentToNext()
    {
        return collectionView.MoveCurrentToNext();
    }

    public bool MoveCurrentToPrevious()
    {
        return collectionView.MoveCurrentToPrevious();
    }

    public bool MoveCurrentTo(object item)
    {
        return collectionView.MoveCurrentTo(item);
    }

    public bool MoveCurrentToPosition(int position)
    {
        return collectionView.MoveCurrentToPosition(position);
    }

    public object AddNew()
    {
        return collectionView.AddNew();
    }

    public void CommitNew()
    {
        collectionView.CommitNew();
    }

    public void CancelNew()
    {
        collectionView.CancelNew();
    }

    public void RemoveAt(int index)
    {
        collectionView.RemoveAt(index);
    }

    public void Remove(object item)
    {
        collectionView.Remove(item);
    }

    public void EditItem(object item)
    {
        collectionView.EditItem(item);
    }

    public void CommitEdit()
    {
        collectionView.CommitEdit();
    }

    public void CancelEdit()
    {
        collectionView.CancelEdit();
    }
}

最后是用法:

ICollectionView<Person> PersonCollectionView { get; }

在构造函数中:

var view = (ListCollectionView) CollectionViewSource.GetDefaultView(PersonCollection);
PersonCollectionView = new GenericCollectionView<Person>(view);
于 2019-01-23T11:22:06.800 回答
0

d:DataContext="{d:DesignInstance Type=lcl:ViewModel}"> 和 GenericCollectionView 都不能直接用于具有 CollectionViewSource 的 DataGrid。

    <DataGrid AutoGenerateColumns="False"
              ItemsSource="{Binding collectionViewSource.View}" 
              SelectedItem="{Binding SelectedRow}" 

我们不能设置“d:DataContext”;因为,我们经常需要将多个属性绑定到我们的视图模型。

CollectionViewSource 创建新的 ListCollectionView,每次设置 Source 属性时都会在运行时实例化。由于设置 Source 属性是刷新一系列行的唯一合理方法,因此我们不能保留 GenericCollectionView。

我的解决方案可能非常明显,但我放弃了 CollectionViewSource。通过创建属性

private ObservableCollection<ListingGridRow> _rowDataStoreAsList;
public GenericCollectionView<ListingGridRow> TypedCollectionView
{
  get => _typedCollectionView;
  set { _typedCollectionView = value; OnPropertyChanged();}
}

public void FullRefresh()
{
    var listData = _model.FetchListingGridRows(onlyListingId: -1);
    _rowDataStoreAsList = new ObservableCollection<ListingGridRow>(listData);
    var oldView = TypedCollectionView;
    var saveSortDescriptions = oldView.SortDescriptions.ToArray();
    var saveFilter = oldView.Filter;
    TypedCollectionView = new GenericCollectionView<ListingGridRow>(new ListCollectionView(_rowDataStoreAsList));
    var newView = TypedCollectionView;
    foreach (var sortDescription in saveSortDescriptions)
    {
        newView.SortDescriptions.Add(new SortDescription()
        {
            Direction = sortDescription.Direction,
            PropertyName = sortDescription.PropertyName
        });
    }
    newView.Filter = saveFilter;
}
internal void EditItem(object arg)
{
    var view = TypedCollectionView;
    var saveCurrentPosition = view.CurrentPosition;
    var originalRow = view.TypedCurrentItem;
    if (originalRow == null)
        return;
    var listingId = originalRow.ListingId;
    var rawListIndex = _rowDataStoreAsList.IndexOf(originalRow);
    // ... ShowDialog ... DialogResult ...
    var lstData = _model.FetchListingGridRows(listingId);
    _rowDataStoreAsList[rawListIndex] = lstData[0];
    view.MoveCurrentToPosition(saveCurrentPosition);
    view.Refresh();
}

添加后 public T TypedCurrentItem => (T)collectionView.CurrentItem; 到 Maxence 提供的 GenericCollectionView。

于 2019-11-17T16:23:16.733 回答