Я ОЧЕНЬ новичок в WPF и все еще пытаюсь понять привязку в XAML.
Я хотел бы заполнить поле со списком значениями коллекции строк в my.settings. Я могу сделать это в таком коде:
Me.ComboBox1.ItemsSource = My.Settings.MyCollectionOfStrings
... и это работает.
Как я могу сделать это в моем 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>
Обратите внимание на следующие аспекты:
Возможно. В C# я делаю это так (для простого bool):
IsExpanded = "{Binding Source = {StaticResource Settings}, Mode=TwoWay, Path=Default.ASettingValue}"
Я определяю статический ресурс «Настройки» в моем 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>
Ваш путь может быть другим; в C# вы получаете доступ к настройкам приложения в своем приложении через
DefaultNamespace.Properties.Settings.Default.ASettingValue
Понятно!
<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# для этого расширения разметки в моем блоге здесь: http://www.thomaslevesque.com/2008/11/18/wpf-binding-to-application-settings-using-a-markup-extension/
Вы также можете сохранить список в виде строки с разделителями в настройках, а затем использовать конвертер.
<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();
Здесь может быть лучший ответ, но прошло два года с тех пор, как эта проблема была свежа в моей голове, и я редко работаю с WPF сейчас. так что я отмечу здесь свой последний пост как ответ.