假设我们有一个WPF ComboBox,并希望使用ObjectDataProvider填充它。
<ObjectDataProvider ObjectType="{x:Type provider:DataProviderProxy}" x:Key="BLDataProvider">
</ObjectDataProvider>
<ObjectDataProvider x:Key="InstallDriverProvider"
ObjectInstance="{StaticResource BLDataProvider}"
MethodName="GetInstallDrivers"
IsAsynchronous="True">
</ObjectDataProvider>
<ComboBox Grid.Row="0" Grid.Column="1"
IsEditable="False"
AlternationCount="2"
IsTextSearchEnabled="True"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding Source={StaticResource InstallDriverProvider}}"
SelectedItem="{Binding Path=InstallDriverPlugin, Mode=TwoWay}"
SelectedValue="{Binding Path=InstallDriverPlugin.Name, Mode=TwoWay}"
SelectedValuePath="id"
...如果GetInstallDrivers()方法调用一些异步返回的服务器方法,比如来自web服务的响应,那么如何填充组合框呢?如何在响应到达后填充组合框?
发布于 2011-12-19 22:20:25
如果您想异步填充组合框,那么使用ObjectDataProvider不是最好的主意。而是使用ViewModel (和MVVM模式),它将combobox数据源作为一个可观察的集合成员属性。然后只需异步获取数据,然后将其发送到UI线程并填充集合。
发布于 2011-12-20 07:08:41
最后,我找到了一个可行的解决方案。也许它不是最好的,但它是有效的,并且维护集中在DataProvider上的一个地方。
我使用了多绑定、MultiValueConverter、DataObjectProvider。首先,我使用INotifyPropertyChanged INotifyPropertyChanging扩展并实现了我的代理类。在那之后,我添加了一个属性来包含结果,然后更改了XAML。
public class DataProviderProxy : INotifyPropertyChanged, INotifyPropertyChanging
{
private BusinessLayer BL;
private List<Transfer.InstallDriverPlugin> _InstallDrivers = new List<Transfer.InstallDriverPlugin>();
public List<Transfer.InstallDriverPlugin> InstallDrivers
{
get
{
return _InstallDrivers;
}
set
{
if (_InstallDrivers != value)
{
RaisePropertyChanging("InstallDrivers");
_InstallDrivers = value;
RaisePropertyChanged("InstallDrivers");
}
}
}..。然后,我放置了一个通用方法来向服务器发送请求并检索数据
public List<Transfer.InstallDriverPlugin> GetInstallDrivers()
{
RequestContext rq = App.BL.GetInstallPlugins("DATA_PROVIDER_InstallDrivers");
App.BL.Admin.SetRequestCustomData(rq, new object[] { });
return InstallDrivers;
}..。处理来自服务器的响应的方法
public void ProcessResponse(ResponseContext rc)
{
// Response filter
...
#region Parse result by command
switch (rc.Command)
{
case AgentCommands.GetInstallPlugins:
if (rc.UserToken == "DATA_PROVIDER_InstallDrivers")
{
App.BL.Admin.ConsumeRequest(rc);
InstallDrivers = (List<Transfer.InstallDriverPlugin>)rc.result;
}
break;..。在XAML中
<ObjectDataProvider ObjectType="{x:Type provider:DataProviderProxy}" x:Key="BLDataProvider">
</ObjectDataProvider>
<ObjectDataProvider x:Key="InstallDriverProvider"
ObjectInstance="{StaticResource BLDataProvider}"
MethodName="GetInstallDrivers"
IsAsynchronous="True">
</ObjectDataProvider>
<ComboBox Grid.Row="0" Grid.Column="1"
IsEditable="False"
AlternationCount="2"
IsTextSearchEnabled="True"
IsSynchronizedWithCurrentItem="True"
DataContext="{StaticResource BLDataProvider}"
SelectedItem="{Binding Path=InstallDriverPlugin, Mode=TwoWay}"
SelectedValue="{Binding Path=InstallDriverPlugin.Name, Mode=TwoWay}"
SelectedValuePath="id"
Background="LightGreen"
MinHeight="29"
KeyDown="ComboBoxKeyDownHandler"
SelectionChanged="ComboBox_SelectionChanged">
<ComboBox.ItemsSource>
<MultiBinding Converter="{StaticResource InstDrvConverter}">
<Binding Source="{StaticResource InstallDriverProvider}"/>
<Binding Path="InstallDrivers" Source="{StaticResource BLDataProvider}"/>
</MultiBinding>
</ComboBox.ItemsSource>
</ComboBox>第一个绑定调用metod来检索异步返回结果并填充属性的日期。第二个绑定将组合框绑定到属性InstallDrivers.最后,多值转换器总是从第二个绑定中获取值,即属性。
public class InstallDriverConverter : IMultiValueConverter
{
#region IMultiValueConverter Members
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
try
{
return values[1];
}
catch
{
return null;
}
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}我知道它比较简单,但也有几个优点。几乎所有的东西都在XAML中,管理是集中的,如果你已经开发了一个表单并想要填充类似的数据,你可以剪切和粘贴代码并重用它,只需在XAML中做一点定制。
https://stackoverflow.com/questions/8562478
复制相似问题