ComboBox上的SelectedItem绑定未显示选定的值

时间:2016-05-11 10:42:47

标签: c# xaml combobox win-universal-app

我正在尝试构建一个设置页面,以允许用户选择在项目滑动时执行哪些操作,例如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;
}

有关为何失败的任何想法?

2 个答案:

答案 0 :(得分:1)

首先,这是你的方法有什么不对: 您将ItemsSource绑定到与SelectedItem相同的属性,即使使用转换器也很困难,这可能会导致无限更新圈 - 而且您不希望这样。

一遍又一遍地生成相同的静态元素列表似乎有点浪费。不要传递类型的实例,只需将类型本身传递给转换器:

EnumToMembersConverter.cs

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

XAML

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中创建

,而不是使用转换器来创建ItemsSource
public MyViewModel(type enumType)
{
    SourceForItems = Enum.GetValues(enumType);
}

public IEnumerable SourceForItems { get; private set; }