2015-11-20 22 views
8

Tôi đang cố gắng để có được một combobox để làm việc với ràng buộc để cuối cùng tôi có thể sử dụng nó cho một số cài đặt. Tôi có thể lấy các mục để điền từ bộ sưu tập có thể quan sát và liên kết 'SelectedItem' với thuộc tính SelectedItem="{x:Bind SelectedComboBoxOption}"UWP Combobox ràng buộc với tài sản SelectedItem

Nhưng khi tôi thay đổi lựa chọn, điều này không được phản ánh trong hộp văn bản cũng bị ràng buộc với thuộc tính này. Trong mã phía sau nó đặt thuộc tính một lần khi khởi động nhưng không phải khi thay đổi các mục trong hộp tổ hợp. Tôi phải thiếu một cái gì đó nhưng nó không phải là rõ ràng với tôi những gì. Bất kỳ ý tưởng?

Đây là XAML:

<Page 
x:Class="ComboBoxTest.MainPage" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:local="using:ComboBoxTest" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
mc:Ignorable="d"> 

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
    <StackPanel> 
     <ComboBox 
      Name="ComboBox" 
      ItemsSource="{x:Bind ComboBoxOptions}" 
      SelectedItem="{x:Bind SelectedComboBoxOption, Mode=TwoWay}" 
      SelectedValuePath="ComboBoxOption" 
      DisplayMemberPath="ComboBoxHumanReadableOption" 
      Header="ComboBox" > 
     </ComboBox> 
     <TextBlock Name="BoundTextblock" Text="{x:Bind SelectedComboBoxOption}"/> 
    </StackPanel> 
</Grid> 

Và đây là đoạn code sau:

using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.ComponentModel; 
using System.IO; 
using System.Linq; 
using System.Runtime.InteropServices.WindowsRuntime; 
using Windows.Foundation; 
using Windows.Foundation.Collections; 
using Windows.UI.Xaml; 
using Windows.UI.Xaml.Controls; 
using Windows.UI.Xaml.Controls.Primitives; 
using Windows.UI.Xaml.Data; 
using Windows.UI.Xaml.Input; 
using Windows.UI.Xaml.Media; 
using Windows.UI.Xaml.Navigation; 



namespace ComboBoxTest 
{ 

public sealed partial class MainPage : Page, INotifyPropertyChanged 
{ 

    private ObservableCollection<ComboBoxItem> ComboBoxOptions; 

    public MainPage() 
    { 
     this.InitializeComponent(); 
     ComboBoxOptions = new ObservableCollection<ComboBoxItem>(); 
     ComboBoxOptionsManager.GetComboBoxList(ComboBoxOptions); 
    } 

    public class ComboBoxItem 
    { 
     public string ComboBoxOption { get; set; } 
     public string ComboBoxHumanReadableOption { get; set; } 
    } 

    public class ComboBoxOptionsManager 
    { 
     public static void GetComboBoxList(ObservableCollection<ComboBoxItem> ComboBoxItems) 
     { 
      var allItems = getComboBoxItems(); 
      ComboBoxItems.Clear(); 
      allItems.ForEach(p => ComboBoxItems.Add(p)); 
     } 

     private static List<ComboBoxItem> getComboBoxItems() 
     { 
      var items = new List<ComboBoxItem>(); 

      items.Add(new ComboBoxItem() { ComboBoxOption = "Option1", ComboBoxHumanReadableOption = "Option 1" }); 
      items.Add(new ComboBoxItem() { ComboBoxOption = "Option2", ComboBoxHumanReadableOption = "Option 2" }); 
      items.Add(new ComboBoxItem() { ComboBoxOption = "Option3", ComboBoxHumanReadableOption = "Option 3" }); 

      return items; 
     } 
    } 


    string _SelectedComboBoxOption = "Option1"; 
    public string SelectedComboBoxOption 
    { 
     get 
     { 
      return _SelectedComboBoxOption; 
     } 
     set 
     { 
      if (_SelectedComboBoxOption != value) 
      { 
       _SelectedComboBoxOption = value; 
       RaisePropertyChanged("SelectedComboBoxOption"); 
      } 
     } 
    } 

    void RaisePropertyChanged(string prop) 
    { 
     if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(prop)); } 
    } 
    public event PropertyChangedEventHandler PropertyChanged; 
} 
} 

Trả lời

10

Như @Mike Eason và @kubakista cho biết, bạn cần đặt Mode một cách rõ ràng. Nhưng điều này sẽ không khắc phục hoàn toàn vấn đề của bạn.

Trong mã của bạn, SelectedComboBoxOption của bạn là một chuỗi, nhưng SelectedItem là đối tượng ComboBoxItem. Binding a String to SelectedItem sẽ không thay đổi mục đã chọn của ComboBox. Vì vậy, nếu bạn muốn sử dụng SelectedComboBoxOption để nhận và đặt mục đã chọn của ComboBox, bạn cần thay đổi SelectedComboBoxOption thành ComboBoxItem và sử dụng Chuyển đổi trong {x:Bind} để chuyển đổi giữa ObjectComboBoxItem.

Các Chuyển đổi có thể thích:

public class ComboBoxItemConvert : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, string language) 
    { 
     return value; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, string language) 
    { 
     return value as MainPage.ComboBoxItem; 
    } 
} 

Các XAML có thể thích:

<Page ...> 
    <Page.Resources> 
     <local:ComboBoxItemConvert x:Key="ComboBoxItemConvert" /> 
    </Page.Resources> 

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
     <StackPanel> 
      <ComboBox Name="ComboBox" 
         DisplayMemberPath="ComboBoxHumanReadableOption" 
         Header="ComboBox" 
         ItemsSource="{x:Bind ComboBoxOptions}" 
         SelectedItem="{x:Bind SelectedComboBoxOption, Mode=TwoWay, Converter={StaticResource ComboBoxItemConvert}}" 
         SelectedValuePath="ComboBoxOption" /> 
      <TextBlock Name="BoundTextblock" Text="{x:Bind SelectedComboBoxOption.ComboBoxHumanReadableOption, Mode=OneWay}" /> 
     </StackPanel> 
    </Grid> 
</Page> 

Trong code-behind:

public sealed partial class MainPage : Page, INotifyPropertyChanged 
{ 
    private ObservableCollection<ComboBoxItem> ComboBoxOptions; 

    public MainPage() 
    { 
     this.InitializeComponent(); 
     ComboBoxOptions = new ObservableCollection<ComboBoxItem>(); 
     ComboBoxOptionsManager.GetComboBoxList(ComboBoxOptions); 
     SelectedComboBoxOption = ComboBoxOptions[0]; 
    } 
    ... 
    private ComboBoxItem _SelectedComboBoxOption; 

    public ComboBoxItem SelectedComboBoxOption 
    { 
     get 
     { 
      return _SelectedComboBoxOption; 
     } 
     set 
     { 
      if (_SelectedComboBoxOption != value) 
      { 
       _SelectedComboBoxOption = value; 
       RaisePropertyChanged("SelectedComboBoxOption"); 
      } 
     } 
    } 
    ... 
} 

Nếu bạn chỉ muốn hiển thị các mục đã chọn trong TextBlock, có một cách dễ dàng. Chúng tôi có thể liên kết tài sản Text của TextBlock với ComboBox 's SelectedItem. Và xin lưu ý rằng loại của SelectedItemSystem.Object{x:Bind} được nhập mạnh và sẽ giải quyết loại mỗi bước trong một đường dẫn. Nếu loại được trả về không có thành viên, loại sẽ không thành công trong thời gian biên dịch. Vì vậy, chúng ta cần phải xác định một diễn viên để nói ràng buộc các loại thực sự của đối tượng. Nhưng có một issue trong khi đúc lớp lồng nhau trong {x:Bind}. Chúng tôi có thể đặt ComboBoxItem trong số MainPage làm giải pháp thay thế.

namespace ComboBoxTest 
{ 
    public class ComboBoxItem 
    { 
     public string ComboBoxOption { get; set; } 
     public string ComboBoxHumanReadableOption { get; set; } 
    } 

    public sealed partial class MainPage : Page, INotifyPropertyChanged 
    { 
     ... 
    } 
} 

Và trong XAML:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
    <StackPanel> 
     <ComboBox Name="ComboBox" 
        DisplayMemberPath="ComboBoxHumanReadableOption" 
        Header="ComboBox" 
        ItemsSource="{x:Bind ComboBoxOptions}" 
        SelectedValuePath="ComboBoxOption" /> 
     <TextBlock Name="BoundTextblock" Text="{x:Bind ComboBox.SelectedItem.(local:ComboBoxItem.ComboBoxHumanReadableOption), Mode=OneWay}" /> 
    </StackPanel> 
</Grid> 
+0

Điều này hoạt động hoàn hảo! Cảm ơn rất nhiều vì lời giải thích tuyệt vời. Là một người mới, không phải lúc nào cũng dễ hiểu tại sao mọi thứ lại được thực hiện theo một cách nào đó. – RonaldA

+0

@Jay, tôi gặp vấn đề ngược lại. Sau khi khởi tạo, nó sẽ trống và bạn có thể chọn bình thường. Bạn có thể xem xét vấn đề này không? Cảm ơn bạn! http://stackoverflow.com/questions/39090923/why-this-uwp-combobox-can-be-blank-after-initialization-but-works-fine-for-selec – litaoshen

0

Theo mặc định, x:Bind được thiết lập để OneTime. Bạn có thể khắc phục điều này bằng cách chỉ cần đặt chế độ thành OneWay.

Text="{x:Bind SelectedComboBoxOption, Mode=OneWay}" 
+1

Thật không may rằng dường như không tạo sự khác biệt.Bên cạnh đó, vì tôi muốn cuối cùng tải một sở thích và có phản ánh trong combobox, tôi không nên sử dụng: 'Mode = TwoWay'? – RonaldA

+0

@RonaldA Đối với SelectedItem giữ 'Mode = TwoWay' nhưng đối với thuộc tính' Text' của bạn trong 'TextBlock' bạn phải sử dụng' Mode = OneWay'. –

Các vấn đề liên quan