Как реализовать ObservableCollection с ListView? - PullRequest
0 голосов
/ 12 мая 2018
 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 голосов
/ 14 мая 2018

... код работал бы, но у меня не будет никаких изменений в реальном времени после удаления строки, например, с помощью 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>. Вы можете использовать DataView или ObservableCollection<T>, где T обычно является пользовательским типом.

0 голосов

Я использую следующий базовый класс для своих источников данных объекта Я заполняю источник данных на основе адаптера, он может получать данные из SQL, диска, лазури и т. Д.

Класс BusinessKey - это базовый класс, с которым я использую бизнес-объекты, сопоставляется со строкой в ​​таблице или другим идентификатором.

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 - это метод расширения enum, который я использую для проверки состояния рабочего процесса договор

/// <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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...