我創建在WPF我自己的搜索控制。該控件是一個UserControl
,其中包含一個帶搜索參數的區域(例如:搜索特定ID,名稱...)和一個顯示結果的GridView
。
在我的控制中,我有一個dependency property
類型ICommand
其中我綁定命令來執行我的搜索查詢。
public static readonly DependencyProperty SearchCommandProperty =
DependencyProperty.Register("SearchCommand", typeof(ICommand), typeof(SearchControl));
在某個窗口中使用我的控制:
<customControls:SearchControl SearchCommand="{Binding SearchItemsCommand}"
SearchResult="{Binding SearchResult}" />
SearchItemsCommand
在我的ViewModel在哪裏可以找到我的搜索查詢的Command
。 在這個命令中,你可以找到我的查詢來檢索結果。我的ICollection
包含搜索查詢的結果。
代碼的命令
的視圖模型
private DelegateCommand searchItemsCommand;
public DelegateCommand SearchItemsCommand
{
get
{
if (this.searchItemsCommand== null)
this.searchItemsCommand= new DelegateCommand(this.SearchItemsCommandExecuted);
return this.searchItemsCommand;
}
}
private ICollection<VoucherOverviewModel> voucherResults;
private void SearchItemsCommandExecuted()
{
using (DbContext context = new DbContext())
{
var query = (from v in context.Vouchers
join vt in context.VoucherTransactions on new
{
voucherID = v.VoucherID,
type = VoucherTransactionType.Out
} equals new
{
voucherID = vt.VoucherID,
type = vt.Type
}
join vtype in context.VoucherTypes on v.VoucherTypeID equals vtype.VoucherTypeID
join c in context.Customers on vt.CustomerID equals c.CustomerID
join pos in context.PointOfSales on v.PointOfSaleID equals pos.PointOfSaleID
select new VoucherOverviewModel()
{
PointOfSaleID = v.PointOfSaleID,
PointOfSaleName = pos.Name,
VoucherID = v.VoucherID,
VoucherCode = v.Code,
VoucherTypeID = v.VoucherTypeID,
VoucherTypeDescription = vtype.Code,
CustomerID = c.CustomerID,
CustomerName = c.Name,
Value = vt.Value,
UsedValue = context.VoucherTransactions
.Where(x => x.VoucherID == v.VoucherID &&
x.Type == VoucherTransactionType.In)
.Sum(x => x.Value),
CreateDate = vt.Date,
ValidFrom = v.ValidFrom,
ValidUntil = v.ValidUntil,
ParentVoucherID = v.ParentVoucherID,
Comment = v.Comment,
});
foreach (ISearchParameter searchParameter in this.SearchParameters)
{
if (!searchParameter.Value.IsNullOrDefault())
{
switch ((FilterVoucherParameterKey)searchParameter.Key)
{
case FilterVoucherParameterKey.CustomerID:
query = query.Where(x => x.CustomerID == (int)searchParameter.Value);
break;
case FilterVoucherParameterKey.VoucherID:
query = query.Where(x => x.VoucherCode.Contains((string)searchParameter.Value));
break;
case FilterVoucherParameterKey.PointOfSale:
query = query.Where(x => x.PointOfSaleID == (byte)searchParameter.Value);
break;
case FilterVoucherParameterKey.Type:
query = query.Where(x => x.VoucherTypeID == (byte)searchParameter.Value);
break;
}
}
}
this.voucherResults = query.ToList();
}
}
定製控制
public static readonly DependencyProperty SearchCommandProperty =
DependencyProperty.Register("SearchCommand", typeof(ICommand), typeof(SearchControl));
public ICommand SearchCommand
{
get
{
return (ICommand)this.GetValue(SearchCommandProperty);
}
set
{
this.SetValue(SearchCommandProperty, value);
}
}
這是我的依賴項屬性,以便我可以將SearchItemsCommand
綁定到我的自定義控件。 然後我有另一個ICommand
來執行綁定的命令,並在我的自定義控件中顯示加載元素。 當你點擊一個按鈕時,這個LocalSearchCommand
將被執行。
private DelegateCommand localSearchCommand;
public DelegateCommand LocalSearchCommand
{
get
{
if (this.localSearchCommand == null)
this.localSearchCommand = new DelegateCommand(this.LocalSearchCommandExecuted);
return this.localSearchCommand;
}
}
private void LocalSearchCommandExecuted()
{
loadingElement.Visible = true;
Task.Factory.StartNew(() =>
{
this.Dispatcher.Invoke((Action)(() => this.SearchCommand.Execute(null)));
})
.ContinueWith(t =>
{
if (t.IsCompleted)
{
t.Dispose();
}
});
}
問題
我希望在執行查詢時與用戶進行交互以顯示加載元素。爲了顯示這個元素,我必須將其設置爲visible
。 現在的問題是,當我將它設置爲可見並想要執行搜索命令時,我的整個UI凍結。從數據庫中提取結果並在GridView
中生成結果後,然後才顯示我的加載元素。我明白爲什麼發生這種情況,我試圖用Task
來解決這個問題。
loadingElement.Visible = true;
Task.Factory.StartNew(() =>
{
this.Dispatcher.Invoke((Action)(() => this.SearchCommand.Execute(null)));
})
.ContinueWith(t =>
{
if (t.IsCompleted)
{
t.Dispose();
}
});
我必須使用Dispatcher
我Task
執行SearchCommand,因爲它是由UI線程擁有。 但由於使用Dispatcher
類,我遇到了和以前一樣的問題。我的加載元素僅在查詢已執行時才顯示,因爲Dispatcher
在UI線程上執行搜索命令。 在不使用Dispatcher
類的,它給了我下面的錯誤:
The calling thread cannot access this object because a different thread owns it.
我上線這個錯誤:
return (ICommand)this.GetValue(SearchCommandProperty);
即使有一個空SearchItemsCommandExecuted
方法,發生錯誤。
我已經嘗試過
我嘗試設置
Task
的TaskScheduler
到TaskScheduler.FromCurrentSynchronizationContext()
我用了很多
BeginInvoke
和Invoke
組合。- 我試着在
Task
中設置加載元件的Visibility
。
但是以上都沒有奏效。
我怎樣才能解決我的問題,從而使加載部件所示,當執行查詢時。我錯過了什麼明顯的東西?
在此先感謝!
Loetn
爲什麼你需要在'Dispatcher'中調用'SearchCommand'? –
@SriramSakthivel因爲它給了我下面的錯誤:'調用線程不能訪問這個對象,因爲一個不同的線程擁有它.'使用'Dispatcher'它執行命令,沒有它給了我這個錯誤。 – Loetn
因此,您需要在'SearchCommand'中發佈代碼。這會有所幫助。 –