2011-12-19 36 views
0

假設我們有一個WPF組合框並希望使用ObjectDataProvider來填充它。如何使用ObjectDataProvider綁定WPF組合框

<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服務的響應怎麼會是可能的填充組合框一些服務器的方法? 如何在響應到達後填充組合框?

回答

1

如果要異步填充組合框,那麼使用ObjectDataProvider並不是最好的辦法。但是改爲使用ViewModel(和MVVM模式),它將combobox數據源作爲可觀察的集合成員屬性。然後簡單地異步獲取數據,然後將其發佈到UI線程並填充集合。

+0

我同意這不是最好的主意,但我想使用ObjectDataProvider,因爲我重用了與數據庫交談的代碼,所以每次調用都幾乎立即返回。當我使用NamedPipes從數據庫更改爲服務器時,必須實施一些請求/響應通信以保持原始代碼不變。看我的竅門。 – Patrik 2011-12-19 15:16:20

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中進行一些自定義即可。