如何使用ListView实现ObservableCollection?

时间:2018-05-12 10:55:36

标签: c# wpf

 private ObservableCollection<DataView> _list;

    public ObservableCollection<DataView> List
    {
        get { return _list; }
        private set
        {
            _list = value;
        }
    }


    public TestViewModel()
    {
        DeleteButtonCommand = new DelegateCommand(somethingABC);
        DataTable dt = new DataTable();
        using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["StringConnexion"].ConnectionString))
        {
            SqlDataAdapter adapter = new SqlDataAdapter();
            adapter.SelectCommand = new SqlCommand("Select * from dbo.users", connection);
            adapter.Fill(dt);
        }
        List = dt.DefaultView;
    }

    public void somethingABC()
    {

        List.Delete(2);
    }

如果我只是简单地将List声明为DataView(没有ObversableCollection),那么代码就可以工作了,但是在使用SomethingABC()删除行之后我将不会有任何实时更改。

我现在在List = dt.DefaultView;中遇到的错误是:

  

无法将类型'System.Data.DataView'隐式转换为'System.Collections.ObjectModel.ObservableCollection'

XAML:

 <ListView  ItemsSource="{Binding List}">
            <ListView.DataContext>
                <local:TestViewModel/>
            </ListView.DataContext>

            <ListView.View>
                <GridView>
                    <GridViewColumn DisplayMemberBinding="{Binding Path=Login}" Header="Name" Width="100"/>
                    <GridViewColumn DisplayMemberBinding="{Binding Path=password}" Header="Password" Width="100"/>
                    <GridViewColumn DisplayMemberBinding="{Binding Path=Permission}" Header="Permission" Width="110"/>
                    <GridViewColumn DisplayMemberBinding="{Binding Path=locked_account}" Header="Compte fermé" Width="150"/>
                </GridView>
            </ListView.View>
        </ListView>

2 个答案:

答案 0 :(得分:0)

我为对象数据源使用以下基类 我根据适配器填充数据源,这可以从SQL,磁盘,azure等获取数据

类BusinessKey是我使用Business对象,映射到表中的行或其他标识符的基类。

public class ObjectDataSource<T> : BindingList<T>
    where T: BusinessKey
{
    System.Threading.ReaderWriterLockSlim loc;

    public ObjectDataSource()
    {
        loc = new System.Threading.ReaderWriterLockSlim(System.Threading.LockRecursionPolicy.NoRecursion);

    }


    protected override void OnListChanged(ListChangedEventArgs e)
    {
        base.OnListChanged(e);            
    }
    protected void Database_OnRemove(T[] e)
    {
        loc.EnterWriteLock();
        try
        {
            foreach (var item in e)
            {
                var ix = Find(item);
                if(ix>=0)
                    OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, ix));
                Data.Remove(item);
            }
        }
        finally
        {
            if(loc.IsWriteLockHeld)
                loc.ExitWriteLock();
        }


    }

    protected void Database_OnAdd(T[] e)
    {
        foreach (var item in e)
            Data.Add(item);


        loc.EnterWriteLock();
        try
        {
            foreach (var item in e)
            {
                Data.Add(item);
                var ix = Find(item);
                if (ix >= 0)
                    OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, ix));
            }
        }
        finally
        {
            if (loc.IsWriteLockHeld)
                loc.ExitWriteLock();
        }

    }

    protected IDataSource<T>  Database { get; }
    protected BindingList<T> Data { get; set; }

    protected override bool SupportsSearchingCore => true;
    protected override bool IsSortedCore => false;
    protected override bool SupportsChangeNotificationCore => true;

    protected override int FindCore(PropertyDescriptor prop, object key)
    {
        int result = -1;
        if (key == null)
            return result;


        PropertyInfo propInfo = typeof(T).GetProperty(prop.Name);
        if(propInfo==null)

        loc.EnterReadLock();
        try
        {
            T item;
            Parallel.For(0, Items.Count, (x,state) => 
            {
                item = Items[x];
                if (propInfo.GetValue(item, null).Equals(key))
                    result =x;
                state.Break();

            });

            }
        finally
        {
            if (loc.IsReadLockHeld)
                loc.ExitReadLock();
        }              

        return result;
    }

    protected int Find(BusinessKey item )
    {
        int result = -1;
        if (item == null)
            return result;


        loc.EnterReadLock();
        try
        {

            Parallel.For(0, Items.Count, (x, state) =>
            {
                if (item.ID==item.ID)
                    result = x;
                state.Break();

            });

        }
        finally
        {
            if (loc.IsReadLockHeld)
                loc.ExitReadLock();
        }

        return result;
    }



}

使用它我只是实例化一个管理这种业务对象的细节的类

以下是重复使用的小样本:

/// <summary>
/// A datasoure that provides access to trade grid data items
/// </summary>
internal class TradeGridDatasorce: ObjectDataSource<TSContract>
{
    readonly ContractRepository rep;

    public TradeGridDatasorce()            
    {
        rep = ContractRepository.Instance;

        Parallel.ForEach(rep.Values, (contract) => {
            contract.OnEnteredTradeGrid += Contract_OnEnteredTradeGrid;
            contract.OnLeftTradeGrid += Contract_OnLeftTradeGrid;


            if (contract.State.IsSet(ContractStates.IsInAnTransaction))
            {
                base.Add(contract);
                base.OnAddingNew(new System.ComponentModel.AddingNewEventArgs(contract));
            }
            rep.OnAdd += Rep_OnAdd;
        });
    }
...

}

Is Set是一个枚举扩展方法,用于检查a的工作流状态 合同

/// <summary>
/// update the flags set for ContractStates and remove a  given state flag
/// </summary>
/// <param name="states">the enum to test</param>
/// <param name="InState">the state to test for</param>
/// <returns>True if flag is set</returns>
public static bool IsSet(this ContractStates item, ContractStates InState)
{
   return (item & InState) != 0;
}

答案 1 :(得分:0)

  

...代码会有效但我在使用SomethingABC()删除行后却没有任何实时更改。

是。您可以从DataTable动态删除行,并自动刷新视图。这应该有效:

private DataView _list;
public DataView List
{
    get { return _list; }
    private set
    {
        _list = value;
    }
}

public TestViewModel()
{
    DeleteButtonCommand = new DelegateCommand(somethingABC);
    DataTable dt = new DataTable();
    using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["StringConnexion"].ConnectionString))
    {
        SqlDataAdapter adapter = new SqlDataAdapter();
        adapter.SelectCommand = new SqlCommand("Select * from dbo.users", connection);
        adapter.Fill(dt);
    }
    List = dt.DefaultView;
}

public void somethingABC()
{
    List.Table.Rows.RemoveAt(0); //remove the first row
}

使用ObservableCollection<DataView>毫无意义。您可以使用DataViewObservableCollection<T>,其中T通常是自定义类型。