WPF将My.Settings集合绑定到组合框项目

WPF将My.Settings集合绑定到组合框项目,wpf,binding,Wpf,Binding,我对WPF非常陌生,仍然在尝试用XAML绑定 我想用my.settings中字符串集合的值填充组合框。我可以用如下代码实现: Me.ComboBox1.ItemsSource=My.Settings.myCollectionOfsString …而且很有效 如何在XAML中执行此操作?可能吗 谢谢是的,您可以(而且大部分情况下应该)在XAML中声明绑定,因为这是WPF中最强大的功能之一 在您的情况下,要将ComboBox绑定到自定义设置之一,可以使用以下XAML: <Window x:Cl

我对WPF非常陌生,仍然在尝试用XAML绑定

我想用my.settings中字符串集合的值填充组合框。我可以用如下代码实现:

Me.ComboBox1.ItemsSource=My.Settings.myCollectionOfsString

…而且很有效

如何在XAML中执行此操作?可能吗


谢谢

是的,您可以(而且大部分情况下应该)在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命名空间,该命名空间指向“Settings”类所在的.NET命名空间,以便在XAML中引用它
  • 我们使用标记扩展{Binding}在XAML中声明绑定
  • 我们使用标记扩展“Static”来表示希望引用XAML中的Static('shared')类成员
    • 这是可能的。在C#中,我是这样做的(对于一个简单的bool):

      我在App.xaml的应用程序中定义静态资源“设置”。因此,资源:

      <!-- 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>
      
      明白了

      <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中之后,我会理解为什么这样做。

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

      <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#代码:

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

      <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);
       }
      }
      

      这里可能有更好的答案,但两年前这个问题在我脑海中浮现,我现在很少与WPF合作。所以我将在这里标记我的最后一篇文章作为答案。WTF???为什么不把恩里科的答案标为答案,而不是把它复制过来,然后标上你自己的答案呢?偷东西不好,m'kay?!
      <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>
      
      <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();