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>
答案 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>
毫无意义。您可以使用DataView
或ObservableCollection<T>
,其中T通常是自定义类型。