【问题标题】:Two way binding settings problem双向绑定设置问题
【发布时间】:2010-12-17 16:17:51
【问题描述】:

我在使用与列表选择器的两种方式绑定时遇到问题。我可以使用 c# 设置值,但不能在 xaml 中的 SelectedItem=".." 中设置。绑定返回正确的值(并且是列表选择器中的值),因为我通过将文本分配给文本块来发送文本。

当页面加载时,listpicker 上使用的绑定会导致System.ArgumentOutOfRangeException

我用来设置它的代码是:

    // Update a setting value. If the setting does not exist, add the setting.
    public bool AddOrUpdateValue(string key, Object value)
    {
        bool valueChanged = false;

        try
        {
            // If new value is different, set the new value
            if (settingsStorage[key] != value)
            {
                settingsStorage[key] = value;
                valueChanged = true;
            }
        }
        catch (KeyNotFoundException)
        {
            settingsStorage.Add(key, value);
            valueChanged = true;
        }
        catch (ArgumentException)
        {
            settingsStorage.Add(key, value);
            valueChanged = true;
        }
        catch (Exception e)
        {
            Console.WriteLine("Exception occured whilst using IsolatedStorageSettings: " + e.ToString());
        }

        return valueChanged;
    }


    // Get the current value of the setting, if not found, set the setting to default value.
    public valueType GetValueOrDefault<valueType>(string key, valueType defaultValue)
    {
        valueType value;

        try
        {
            value = (valueType)settingsStorage[key];
        }
        catch (KeyNotFoundException)
        {
            value = defaultValue;
        }
        catch (ArgumentException)
        {
            value = defaultValue;
        }

        return value;
    }

    public string WeekBeginsSetting
    {
        get
        {
            return GetValueOrDefault<string>(WeekBeginsSettingKeyName, WeekBeginsSettingDefault);
        }
        set
        {
            AddOrUpdateValue(WeekBeginsSettingKeyName, value);
            Save();
        }
    }

在 xaml 中:

<toolkit:ListPicker x:Name="WeekStartDay" 
                    Header="Week begins on" 
                    SelectedItem="{Binding Source={StaticResource AppSettings},
                                           Path=WeekBeginsSetting, 
                                           Mode=TwoWay}">
    <sys:String>monday</sys:String>
    <sys:String>sunday</sys:String>
</toolkit:ListPicker>

StaticResource AppSettings 是来自单独 .cs 文件的资源。

<phone:PhoneApplicationPage.Resources>
    <local:ApplicationSettings x:Key="AppSettings"></local:ApplicationSettings>
</phone:PhoneApplicationPage.Resources>

提前致谢

【问题讨论】:

  • 你写{StaticResource AppSettings}是什么意思?它是在 XAML 或 static class 中定义的 resource 的名称吗?
  • 是的对不起我忘了提到 AppSettings 是一个单独的类文件
  • 是静态类吗?您是否将{x:Static AppSettings.WeekBeginsSetting} 与您当前的绑定混淆了?因为 Silverlight 不支持{x:Static}。
  • 对我来说同样的问题,SelectedItem 和 SelectedIndex。特别是 Jame 在下面的评论 我可以让 SelectedIndex 工作,但它只是突出显示该项目并且在列表选择器处于非活动状态时不显示它 - 而是显示列表选择器中的第一个值。看看是否有人知道如何解决这个问题。

标签: c# silverlight xaml windows-phone-7


【解决方案1】:

我使用 Reflector 找到了这个异常的来源。在 ListPicker.cs 中,以下方法被覆盖。

protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)

在此方法中,如果设置了 SelectedItem 并且 SelectedIndex 为 -1(除非在加载之前设置),则以下行将导致异常。如果未设置 SelectedItem,则永远不会到达此行(因此也不例外)。

else if (!object.Equals(base.get_Items().get_Item(this.SelectedIndex), this.SelectedItem))

为了解决这个问题(直到他们解决这个问题)我有一些建议。

解决方法 1

如果您知道将由 TwoWay 绑定生成的起始索引,那么您也可以设置 SelectedIndex 属性,并且 TwoWay 绑定将起作用

<toolkit:ListPicker x:Name="WeekStartDay"
                    Header="Week begins on"
                    SelectedItem="{Binding Source={StaticResource AppSettings},
                                           Path=WeekBeginsSetting,
                                           Mode=TwoWay}"
                    SelectedIndex="1">
    <sys:String>monday</sys:String>
    <sys:String>sunday</sys:String>
</toolkit:ListPicker> 

解决方法 2

使用 Loaded 事件并从那里设置绑定

<toolkit:ListPicker x:Name="WeekStartDay"
                    Header="Week begins on"
                    Loaded="WeekStartDay_Loaded">
    <sys:String>monday</sys:String>
    <sys:String>sunday</sys:String>
</toolkit:ListPicker>

private void WeekStartDay_Loaded(object sender, RoutedEventArgs e)
{
    Binding binding = new Binding();
    binding.Source = this.Resources["AppSettings"] as ApplicationSettings;
    binding.Path = new PropertyPath("WeekBeginsSetting");
    binding.Mode = BindingMode.TwoWay;
    WeekStartDay.SetBinding(ListPicker.SelectedItemProperty, binding);
}

【讨论】:

  • 感谢详细了解此内容。我想我会采用解决方法 #2。
【解决方案2】:

您是否正在触发相关的属性更改事件?

确保 SelectedItem 可以有两种方式绑定。如果没有,请尝试定义 ItemContainerStyle 并将 IsSelected 属性绑定到对象上的相应属性。然后获取选定项变得微不足道。

【讨论】:

  • 哎呀,我忘了提到我遇到的问题是在设置列表选择器时它会抛出一个System.ArgumentOutOfRangeException
【解决方案3】:

如果 AppSettings 是一个集合,那么这将不起作用。您需要将 SelectedItem 绑定到一个标量值,不幸的是 WP7 上的“Silverlight 3.7”不支持绑定中的索引器。

另外,请不要在程序中使用异常作为流控制,而是这样做:

    try
    {
        // If new value is different, set the new value
        if(!settingsStorage.ContainsKey(key))
        {
            settingsStorage.Add(key, value);
            valueChanged = true;
        }
        else if(settingsStorage[key] != value)
        {
            settingsStorage[key] = value;
            valueChanged = true;
        }
    }
    catch (Exception e)
    {
        Console.WriteLine("Exception occured whilst using IsolatedStorageSettings: " + e.ToString());
    }

【讨论】:

  • 谢谢,我可以让 SelectedIndex 工作,但它只是突出显示该项目并且在列表选择器处于非活动状态时不显示它 - 而是显示列表选择器中的第一个值。
【解决方案4】:

我没有使用绑定,而是在页面加载时简单地设置选定项,并使用 selectionchanged 事件处理程序来更新值而无需确认(有一个保存按钮)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-30
    • 1970-01-01
    • 2020-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-20
    • 1970-01-01
    相关资源
    最近更新 更多