WPF Binding My.Settings collection to Combobox items

前端 未结 5 1935
长情又很酷
长情又很酷 2021-02-15 16:18

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

I\'d like to populate a combobox with the values of a string collection in my.settings. I

相关标签:
5条回答
  • 2021-02-15 16:46

    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();
    
    0 讨论(0)
  • 2021-02-15 16:52

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

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

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

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

    DefaultNamespace.Properties.Settings.Default.ASettingValue
    
    0 讨论(0)
  • 2021-02-15 16:58

    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.

    0 讨论(0)
  • 2021-02-15 17:00

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

    In your case, to bind the ComboBox to one of your custom settings you would use the following 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
    0 讨论(0)
  • 2021-02-15 17:07

    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/

    0 讨论(0)
提交回复
热议问题