我正在尝试构建一个设置页面,以允许用户选择在项目滑动时执行哪些操作,例如Outlook应用。
为此,我创建了一个包含可用操作的enum
,并将其绑定到ComboBox
。
一切正常,用户可以选择动作并正确保存他的选择。问题是当我导航到页面时ComboBox
没有显示所选项目,它仅在选择后显示。
这意味着如果用户更改了选择,则会更新ComboBox
,但导航时所选项目会显示为空白。
这是我的代码:
(XAML)
<ComboBox x:Uid="LeftActionComboBox"
Grid.Row="0"
HorizontalAlignment="Stretch"
SelectedItem="{Binding LeftSwipeActionType, Mode=TwoWay, Converter={StaticResource StringToSwipeActionTypesConverter}}"
ItemsSource="{Binding LeftSwipeActionType, Converter={StaticResource EnumToStringListConverter}}"/>
(VM Property)
public SwipeActionTypes LeftSwipeActionType
{
get { return _settings.LeftSwipeActionTypeProperty; }
set
{
_settings.LeftSwipeActionTypeProperty = value;
// RaisePropertyChanged causes a StackOverflow, but not using it is not the problem since the ComboBox is empty only before set
}
}
(转换器StringToSwipeActionTypesConverter
,已准备好本地化)
// Returns localized string value for the Enum
public object Convert(object value, Type targetType, object parameter, string language)
{
var enumValue = (SwipeActionTypes) value;
switch (enumValue)
{
case SwipeActionTypes.Copy:
return App.ResourceLoader.GetString("CopySwipeActionName");
case SwipeActionTypes.Delete:
return App.ResourceLoader.GetString("DeleteSwipeActionName");
default:
throw new ArgumentOutOfRangeException();
}
}
// Parses the localized string into the enum value
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
var stringValue = (string) value;
if (stringValue.Equals(App.ResourceLoader.GetString("CopySwipeActionName")))
{
return SwipeActionTypes.Copy;
}
if (stringValue.Equals(App.ResourceLoader.GetString("DeleteSwipeActionName")))
{
return SwipeActionTypes.Delete;
}
return null;
}
(转换器EnumToStringListConverter
)
public object Convert(object value, Type targetType, object parameter, string language)
{
var valueType = value.GetType();
return Enum.GetNames(valueType).ToList();
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return value;
}
有关为何失败的任何想法?
答案 0 :(得分:1)
首先,这是你的方法有什么不对:
您将ItemsSource
绑定到与SelectedItem
相同的属性,即使使用转换器也很困难,这可能会导致无限更新圈 - 而且您不希望这样。
一遍又一遍地生成相同的静态元素列表似乎有点浪费。不要传递类型的实例,只需将类型本身传递给转换器:
public class EnumToMembersConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
return Enum.GetValues((Type)value).ToList();
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return DependencyProperty.UnsetValue;
}
}
ItemsSource="{Binding Source={x:Type whateverNamespace:SwipeActionTypes}, Converter={StaticResource EnumToMembersConverter}}"
这将为您提供SwipeActionTypes
的所有值,因此您可以直接绑定它,而无需再次转换回来。
SelectedItem="{Binding LeftSwipeActionType, Mode=TwoWay}"
将ComboBox用于字符串以外的类型没有任何问题,所以让它成为您进一步步骤的基础:
<ComboBox x:Uid="LeftActionComboBox"
Grid.Row="0"
HorizontalAlignment="Stretch"
SelectedItem="{Binding LeftSwipeActionType, Mode=TwoWay}"
ItemsSource="{Binding Source={x:Type whateverNamespace:SwipeActionTypes}, Converter={StaticResource EnumToMembersConverter}}"/>
您编写所有这些转换的原因可能是因为ComboBox
显示了奇怪的值而不是可读的字符串。不用担心,我们已经有了你的转换器,你只需反转它(将SwipeActionTypes
转换为String
)并将其应用到TextBox:
<ComboBox x:Uid="LeftActionComboBox"
Grid.Row="0"
HorizontalAlignment="Stretch"
SelectedItem="{Binding LeftSwipeActionType, Mode=TwoWay}"
ItemsSource="{Binding Source={x:Type whateverNamespace:SwipeActionTypes}, Converter={StaticResource EnumToMembersConverter}}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=., Converter = {StaticResource SwipeActionTypesStringConverter}}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
注意,我没有运行此代码,因此您可能需要相应地调整使用的命名空间
答案 1 :(得分:1)
您获得StackOverflow异常的原因是因为每次更改LeftSwipeActionType
属性时,您都会更改ComboBox的ItemsSource,它会更改SelectedItem,它会触发更改ItemsSource的INotifyPropertyChanged,依此类推。< / p>
一旦停止为ItemsSource和SelectedItem使用相同的属性,则将设置正确的初始选择。
您应该只在ViewModel中创建
,而不是使用转换器来创建ItemsSourcepublic MyViewModel(type enumType)
{
SourceForItems = Enum.GetValues(enumType);
}
public IEnumerable SourceForItems { get; private set; }