条件组合框与字符串存储绑定

Conditional combobox binding with string storage

我正在尝试构建付款信息表,但 运行 遇到了一些麻烦。

  1. 我有这个 "Country" 组合框,它允许用户 select 国家/地区。
  2. 我还有另一个 "State" ComboBox 让用户 select 国家/地区。
  3. 因为每个国家都有不同的州,ItemSource 取决于 "Country" ComboBox 的 selection。
  4. XAML 的层次结构:TabControl -> Grid -> ComboBoxes

  5. 我还需要将数据存储在一个Profile的实例中class,调用这个profile 1(profiles存储在一个静态的Observable Collection中,调用这个Profiles),程序将包含多个配置文件。

问题:

我很难将其绑定到 State ComboBox,因为我是 WPF 的新手,因此非常感谢任何帮助。非常感谢。

问题是我不知道如何使 State ComboBox ItemSource 有条件地绑定到 ComboBoxSource class 成员,同时与各个配置文件的 State 属性 同步。 (它需要与读取字符串的值同步)

解决方案:

<ComboBox Name="Country" ItemsSource="{Binding Source={x:Static loc:ComboBoxItemSource.Countries}}" SelectedItem="{Binding Path=Country, Mode=TwoWay}">
<ComboBox Name="State" ItemsSource="{Binding States, Mode=TwoWay}" SelectedItem="{Binding Path=State, Mode=TwoWay}">

将此与 "stijn" 的解决方案结合使用,非常感谢! 出于某种原因,如果我使用 "State" ComboBox 的原始属性,selected 选项将不会在运行时正确显示。

主要思想是使用 SelectedItem 而不是 SelectedValue 和 SelectedValuePath

原代码如下:

XAML:

<ComboBox Name="Country" Grid.Row="0" Grid.Column="3" SelectedValuePath="Content" SelectedValue="{Binding Country, Mode=TwoWay}" SelectionChanged="Country_SelectionChanged">
    <ComboBoxItem>USA</ComboBoxItem>
    <ComboBoxItem>Canada</ComboBoxItem>
    <ComboBoxItem>Japan</ComboBoxItem>
</ComboBox>
<ComboBox Name="State" Grid.Row="1" Grid.Column="3" SelectedValuePath="Content" SelectedValue="{Binding State, Mode=TwoWay}" ItemsSource="{Binding Source={x:Static loc:ComboBoxItemSource.USStates}}">

代码隐藏:

class Profile
{
    //default values
    private string country = "Canada";

    public string Country
    {
        get { return country; }
        set 
        {
            country = value;
            this.OnPropertyChanged();
        }
    }
    //default values
    private string state = "CA2";

    public string State
    {
        get { return state; }
        set 
        { 
            state = value;
            this.OnPropertyChanged();
        }
    }
}

public class ComboBoxItemSource
{
    public static MTObservableCollection<string> USStates = new MTObservableCollection<string> { "VA", "DC" };
    public static MTObservableCollection<string> CanadaStates = new MTObservableCollection<string> { "CA1", "CA2" };
    public static MTObservableCollection<string> Countries = new MTObservableCollection<string> { "USA", "Canada", "Japan" };       
}

//Some method in the main class:
private void Country_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    Dispatcher.BeginInvoke(new Action(() =>
    {
        if (Profiles.Count > 0)
        {
            //the ComboBox is inside a grid, which is inside a TabControl that displays all the profiles
            Profile item = (Profile)((Grid)((ComboBox)sender).Parent).DataContext;
            ContentPresenter cp = Tabs.Template.FindName("PART_SelectedContentHost", Tabs) as ContentPresenter;
            ComboBox g = Tabs.ContentTemplate.FindName("State", cp) as ComboBox;
            if (g.ItemsSource == null) { return; }
            if (((ComboBox)sender).Text == "USA")
            {
                g.ItemsSource = ComboBoxItemSource.USStates;
            }
            else if (((ComboBox)sender).Text == "Canada")
            {
                g.ItemsSource = ComboBoxItemSource.CanadaStates;
            }
        }
    }));
}

不需要 'conditionally bind' 静态变量,也不需要隐藏代码。我建议您在互联网上搜索 'MVVM' 并阅读一些基本教程。

可能的解决方案:提供一个 public IList<string> States 属性 将您的状态组合框绑定到(我认为您不必在这里使用 ObservableCollections)和 setter 中的 Country 将列表设置为适当的状态列表。类似于:

public string Country
{
    get { return country; }
    set 
    {
        country = value;
        SetStatesForCountry( value );
        this.OnPropertyChanged();
    }
}

private IList<string> states;

public IList<string> States
{
  get{ return states; }
  private set { states = value; this.OnPropertyChanged(); } 
}

private void SetStatesForCountry( string selectedCountry )
{
  IList<string> found;
  if( StatesPerCountry.Map.TryGetValue( selectedCountry, out found ) )
  {
    States = found;
  }
  else
  {
    States = null; //or you could set it to "not applicable" or so
  }
}

请注意,我使用字典将州映射到国家,不需要大量的 if/else 子句:

public class StatesPerCountry
{
   public static IDictionary<string,IList<string>> Map = new
     IDictionary<string,IList<string>>
   {
     { "USA", new List<string>{ "a", "b", "c" } },
     { "CAN", new List<string>{ "a", "b", "c" } },
     { "Japan", new List<string>{ "a", "b", "c" } }
   }
}