将My.Settings集合绑定到下拉框的选项中的WPF绑定

8

我对WPF非常陌生,还在努力理解XAML中的绑定。

我想用我的设置中的字符串集合值来填充下拉框。我可以像这样在代码中实现:

Me.ComboBox1.ItemsSource = My.Settings.MyCollectionOfStrings

它是有效的。

那么我怎么在XAML中实现呢?这可能吗?

谢谢!

5个回答

19

是的,你可以(并且在大多数情况下应该)在XAML中声明绑定,因为这是WPF中最强大的特性之一。

对于你的情况,要将ComboBox绑定到你的自定义设置之一,你需要使用以下XAML:

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:p="clr-namespace:WpfApplication1.Properties"
    Title="Window1">
    <StackPanel>
        <ComboBox
            ItemsSource="{Binding Source={x:Static p:Settings.Default}, Path=MyCollectionOfStrings}" />
    </StackPanel>
</Window>

注意以下几个方面:

  • 我们使用了前缀为“p”的XML命名空间,该命名空间指向.NET命名空间,其中“Settings”类位于其中,以便在XAML中引用它。
  • 我们使用标记扩展“{Binding}”来声明XAML中的绑定。
  • 我们使用标记扩展“Static”来表示我们要在XAML中引用一个静态(在VB中为“共享”)类成员。

3

我有一个更简单的解决方案,可以使用自定义标记扩展来实现。在您的情况下,它可以像这样使用:

<Window x:Class="Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:my="clr-namespace:WpfApplication1"
    Title="Window1" Height="90" Width="462" Name="Window1">
    <Grid>
        <ComboBox ItemsSource="{my:SettingBinding MyCollectionOfStrings}" />
    </Grid>
</Window>

你可以在我的博客上找到这个标记扩展的C#代码: http://www.thomaslevesque.com/2008/11/18/wpf-binding-to-application-settings-using-a-markup-extension/


1

这是可能的。在C#中,我会这样做(对于一个简单的布尔值):

IsExpanded="{Binding Source={StaticResource Settings}, Mode=TwoWay, Path=Default.ASettingValue}"

我在App.xaml的Application.Resources中定义了静态资源“Settings”,如下所示:
<!-- other namespaces removed for clarity -->
<Application xmlns:settings="clr-namespace:DefaultNamespace.Properties" >
 <Application.Resources>
  <ResourceDictionary>
   <settings:Settings x:Key="Settings" />
   <!--stuff removed-->
  </ResourceDictionary>
 </Application.Resources>
</Application>

你的路径可能不同;在C#中,你可以通过以下方式访问应用程序设置:

DefaultNamespace.Properties.Settings.Default.ASettingValue

1

明白了!

<Window x:Class="Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:p="clr-namespace:WpfApplication1"
    Title="Window1" Height="90" Width="462" Name="Window1">
    <Grid>
        <ComboBox ItemsSource="{Binding Source={x:Static p:Settings.Default}, Path=MyCollectionOfStrings}" />
    </Grid>
</Window>

感谢大家帮助我达到了一个伟大的“啊哈!”时刻 :-) ……希望在我花更多时间学习WPF后,我能理解为什么这样做。


这里可能有更好的答案,但已经过去两年了,我很少使用WPF,因此我将把我的最后一篇帖子标记为答案。 - Ben Brandt
3
为什么不直接将Enrico的回答标记为答案,而要复制他的回答然后标记自己的答案?抄袭是不好的,好吗?! - Dimitri

0

你也可以将列表作为设置中的分隔字符串存储,然后使用转换器。

<ComboBox ItemsSource="{Binding Default.ImportHistory,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay,Converter={StaticResource StringToListConverter},ConverterParameter=|}" IsEditable="True">
/// <summary>
/// Converts a delimited set of strings to a list and back again. The parameter defines the delimiter
/// </summary>
public class StringToListConverter : IValueConverter {
 /// <summary>
 /// Takes a string, returns a list seperated by {parameter}
 /// </summary>
 public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
     string serializedList = (value ?? string.Empty).ToString(),
            splitter = (parameter ?? string.Empty).ToString();
     if(serializedList.Trim().Length == 0) {
         return value;
     }
     return serializedList.Split(new[] { splitter }, StringSplitOptions.RemoveEmptyEntries);
 }
 /// <summary>
 /// Takes a list, returns a string seperated by {parameter}
 /// </summary>
 public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
     var items = value as IEnumerable;
     var splitter = (parameter ?? string.Empty).ToString();
     if(value == null || items == null) {
         return value;
     }
     StringBuilder buffer = new StringBuilder();
     foreach(var itm in items) {
         buffer.Append(itm.ToString()).Append(splitter);
     }
     return buffer.ToString(0, splitter.Length > 0 ? buffer.Length - splitter.Length : buffer.Length);
 }
}

然后当点击浏览按钮时,您可以将其添加到列表中:

var items = Settings.Default.ImportHistory.Split('|');
if(!items.Contains(dlgOpen.FileNames[0])) {
 Settings.Default.ImportHistory += ("|" + dlgOpen.FileNames[0]);
}
cboFilename.SelectedValue = dlgOpen.FileNames[0];
Settings.Default.Save();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接