条件组合框与字符串存储绑定
Conditional combobox binding with string storage
我正在尝试构建付款信息表,但 运行 遇到了一些麻烦。
- 我有这个 "Country" 组合框,它允许用户 select 国家/地区。
- 我还有另一个 "State" ComboBox 让用户 select 国家/地区。
- 因为每个国家都有不同的州,ItemSource 取决于 "Country" ComboBox 的 selection。
XAML 的层次结构:TabControl -> Grid -> ComboBoxes
我还需要将数据存储在一个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" } }
}
}
我正在尝试构建付款信息表,但 运行 遇到了一些麻烦。
- 我有这个 "Country" 组合框,它允许用户 select 国家/地区。
- 我还有另一个 "State" ComboBox 让用户 select 国家/地区。
- 因为每个国家都有不同的州,ItemSource 取决于 "Country" ComboBox 的 selection。
XAML 的层次结构:TabControl -> Grid -> ComboBoxes
我还需要将数据存储在一个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" } }
}
}