两种方式绑定设置问题

发布于 2024-10-08 07:10:34 字数 2714 浏览 2 评论 0原文

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

当页面加载时,列表选择器上使用的绑定会导致 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>

提前致谢

I am having a problem using two way binding with a listpicker. I am able to set the value using c# but not in the SelectedItem=".." in xaml. The binding is returning the correct value (and is a value in the listpicker) as i have texted it by assigning the text to a textblock.

When the page loads, the binding used on the listpicker causes a System.ArgumentOutOfRangeException

The code i am using to set it is:

    // 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();
        }
    }

And in the 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>

The StaticResource AppSettings is a resource from a seperate .cs file.

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

Thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

盛装女皇 2024-10-15 07:10:34

我使用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);
}

I used Reflector to find the source of this exception. In ListPicker.cs the following method is overridden.

protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)

In this method the following line will cause the exception if SelectedItem is set and SelectedIndex is -1 (which it is unless it's set before it's loaded). If SelectedItem isn't set this line is never reached (hence no exception).

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

To work around this (until they get this fixed) I have some suggestions.

Workaround 1

If you know the starting index which will be produced by the TwoWay binding then you can set the SelectedIndex property as well and the TwoWay Binding will work

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

Workaround 2

Use the Loaded event and set the Binding from there instead

<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);
}
如若梦似彩虹 2024-10-15 07:10:34

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

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

Are you Firing the relevant property changed events?

Make sure that SelectedItem can have a two way binding.If not then try defining an ItemContainerStyle and bind the IsSelected property to a corresponding property on your object.Getting the selected item then becomes trivial.

冬天旳寂寞 2024-10-15 07:10:34

如果 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());
    }

If AppSettings is a collection then this is not going to work. You need to bind SelectedItem to a scalar value and unfortunately the "Silverlight 3.7" on WP7 doesn't support indexers in bindings.

Also, please don't use exceptions as flow control in your program, instead do something like this:

    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());
    }
2024-10-15 07:10:34

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

Instead of using binding I simply set the selecteditem when the page loaded and used a selectionchanged event handler to update the value without confirmation (having a save button).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文