如何使用ObjectDataProvider绑定WPF ComboBox

时间:2011-12-19 14:05:01

标签: wpf combobox

假设我们有一个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服务的响应一样,如何填充组合框? 如何在响应到达后填充组合框?

2 个答案:

答案 0 :(得分:1)

如果要异步填充组合框,那么使用ObjectDataProvider不是最佳选择。但是使用ViewModel(和MVVM模式),它具有组合框数据源作为可观察的集合成员属性。然后只需异步获取数据,然后将其发布到UI线程并填充集合。

答案 1 :(得分:0)

最后,我找到了一个有效的解决方案。也许它不是最好的,但它可以正常工作,并且维护工作集中在DataProvider上的一个位置。

我使用了multibinding,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中进行一些自定义。