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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/204779/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 19:42:42  来源:igfitidea点击:

WPF Binding My.Settings collection to Combobox items

wpfbinding

提问by Ben Brandt

I'm VERY new to WPF, and still trying to wrap my head around binding in XAML.

我对 WPF 非常陌生,并且仍然试图围绕 XAML 中的绑定进行思考。

I'd like to populate a combobox with the values of a string collection in my.settings. I can do it in code like this:

我想用 my.settings 中字符串集合的值填充组合框。我可以在这样的代码中做到这一点:

Me.ComboBox1.ItemsSource = My.Settings.MyCollectionOfStrings

Me.ComboBox1.ItemsSource = My.Settings.MyCollectionOfStrings

...and it works.

...它有效。

How can I do this in my XAML? is it possible?

如何在我的 XAML 中执行此操作?是否可以?

Thanks

谢谢

回答by Enrico Campidoglio

Yes, you can (and should for the most part) declare bindings in XAML, since that's one of the most powerful features in WPF.

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

In your case, to bind the ComboBox to one of your custom settings you would use the following XAML:

在您的情况下,要将 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>

Notice the following aspects:

注意以下几个方面:

  • We declared an XML namespace with the prefix 'p' that points to the .NET namespace where the 'Settings' class lives in order to refer to it in XAML
  • We used the markup extension '{Binding}' in order to declare a binding in XAML
  • We used the markup extension 'Static' in order to indicate that we want to refer to a static ('shared' in VB) class member in XAML
  • 我们声明了一个带有前缀“p”的 XML 命名空间,它指向“设置”类所在的 .NET 命名空间,以便在 XAML 中引用它
  • 我们使用标记扩展“{Binding}”来声明 XAML 中的绑定
  • 我们使用标记扩展“Static”来指示我们想要引用 XAML 中的静态(VB 中的“共享”)类成员

回答by Thomas Levesque

I have a simpler solution for doing that, using a custom markup extension. In your case it could be used like this :

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

<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>

You can find the C# code for this markup extension on my blog here : http://www.thomaslevesque.com/2008/11/18/wpf-binding-to-application-settings-using-a-markup-extension/

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

回答by Thomas Levesque

It is possible. In C#, I do it like this (for a simple bool):

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

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

I define the static resource "Settings" in my App.xaml's Application.Resources thusly:

我这样在 App.xaml 的 Application.Resources 中定义了静态资源“设置”:

<!-- 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>

Your path may be different; in C#, you access app settings in your application via

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

DefaultNamespace.Properties.Settings.Default.ASettingValue

回答by Ben Brandt

Got it!

知道了!

<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>

Thank you all for helping me reach a great "Aha!" moment :-) ...hopefully after I spend some more time in WPF I'll understand why this works.

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

回答by Echilon

You could also store the list as a delimited string in settings then use a converter.

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

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

Then when a browse button is clicked, you can add to the list:

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

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