sensboston
@sensboston

Привязка ComboBox.SelectedIndex к Properties.Settings.Default

Делаю небольшой рефакторинг проекта на WinForms (.NET 4.0 client profile), хочу избавиться от уродливых кусков вроде ручного запоминания SelectedIndex комбо-боксов в settings по событию SelectedIndexChanged (т.е. «прибиндить» к Settings SelectedIndex также, как и TextBox.Text или CheckBox.Checked etc.)
По странной причине, Microsoft не дает возможности «забиндить» SelectedIndex или SelectedValue через UI, однако, если я добавляю такой код:
public MainForm() 
{
    InitializeComponent();
    comboBox1.DataBindings.Add(new Binding("SelectedIndex", Properties.Settings.Default, "SelIndex1", false, DataSourceUpdateMode.OnPropertyChanged));

то все работает, как и предполагалось (т.е. SelectedIndex автоматически запоминается в Properties.Settings.Default.SelIndex1), за исключением одной неприятной вещи: каждое изменение ComboBox-а порождает 6 не фатальных исключений в системных assemblies:
A first chance exception of type 'System.ArgumentOutOfRangeException' occurred in System.Windows.Forms.dll
A first chance exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll
A first chance exception of type 'System.ArgumentOutOfRangeException' occurred in System.dll
A first chance exception of type 'System.ArgumentOutOfRangeException' occurred in System.Windows.Forms.dll
A first chance exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll
A first chance exception of type 'System.ArgumentOutOfRangeException' occurred in System.dll

Думаю, что дело в отсутствии value converter для системного int (проперти SelIndex1 описана как int), но не знаю, как именно пофиксить. Хочется сделать это элегантно (как сделать, как обычно — я знаю :) ). Да, еще нужно, чтобы решение работало под Mono на Linux.
Т.е. что-то вроде расширения стандартных ValueConverters или еще какой хак.
Заранее спасибо!

P.S. Нужно именно под WinForms, не Silverlight или WPF (там это работает «на раз).
  • Вопрос задан
  • 4693 просмотра
Пригласить эксперта
Ответы на вопрос 4
sensboston
@sensboston Автор вопроса
Нашел и пофиксил проблему, но суть ее по прежнему остается вне моего понимания :) У меня на форме есть компонент NumericUpDown, у него был установлен Minimum == 3. Да, еще что важно — у меня свой, custom SettingsProvider (для «портабельности»). Так вот, при изменении ComboBox-а, почему-то падало на

        [global::System.Configuration.UserScopedSettingAttribute()]
        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
        [global::System.Configuration.DefaultSettingValueAttribute("0")]
        public int LogLevel {
            get {
                return ((int)(this["LogLevel"]));
            }
            set {
                this["LogLevel"] = value;
            }
        }


Установка Minimum-а у NumericUpDown в 0 решило проблему. Но странно все это!..

Вот полный
stack trace:
System.Windows.Forms.dll!System.Windows.Forms.NumericUpDown.Value.set(decimal value) + 0x1af bytes
[Native to Managed Transition]
System.dll!System.SecurityUtils.MethodInfoInvoke(System.Reflection.MethodInfo method, object target, object[] args) + 0x65 bytes
System.dll!System.ComponentModel.ReflectPropertyDescriptor.SetValue(object component, object value) + 0x11b bytes
System.Windows.Forms.dll!System.Windows.Forms.Binding.SetPropValue(object value) + 0xdb bytes
System.Windows.Forms.dll!System.Windows.Forms.Binding.PushData(bool force) + 0xa0 bytes
System.Windows.Forms.dll!System.Windows.Forms.BindingManagerBase.PushData(out bool success) + 0x5b bytes
System.Windows.Forms.dll!System.Windows.Forms.PropertyManager.OnCurrentChanged(System.EventArgs ea) + 0x1b bytes
System.Windows.Forms.dll!System.Windows.Forms.BindToObject.PropValueChanged(object sender, System.EventArgs e) + 0x29 bytes
System.dll!System.ComponentModel.PropertyDescriptor.OnValueChanged(object component, System.EventArgs e) + 0x54 bytes
System.dll!System.ComponentModel.ReflectPropertyDescriptor.OnValueChanged(object component, System.EventArgs e) + 0x63 bytes
System.dll!System.ComponentModel.ReflectPropertyDescriptor.OnINotifyPropertyChanged(object component, System.ComponentModel.PropertyChangedEventArgs e) + 0x82 bytes
System.dll!System.Configuration.ApplicationSettingsBase.OnPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) + 0x1a bytes
System.dll!System.Configuration.ApplicationSettingsBase.this[string].set(string propertyName, object value) + 0x96 bytes
> TinyOPDS.exe!TinyOPDS.Properties.Settings.LogLevel.set(int value) Line 239 + 0x37 bytes C#
[Native to Managed Transition]
System.dll!System.SecurityUtils.MethodInfoInvoke(System.Reflection.MethodInfo method, object target, object[] args) + 0x65 bytes
System.dll!System.ComponentModel.ReflectPropertyDescriptor.SetValue(object component, object value) + 0x11b bytes
System.Windows.Forms.dll!System.Windows.Forms.BindToObject.SetValue(object value) + 0x63 bytes
System.Windows.Forms.dll!System.Windows.Forms.Binding.PullData(bool reformat, bool force) + 0x159 bytes
System.Windows.Forms.dll!System.Windows.Forms.Binding.Target_PropertyChanged(object sender, System.EventArgs e) + 0x2c bytes
System.Windows.Forms.dll!System.Windows.Forms.ComboBox.OnSelectedIndexChanged(System.EventArgs e) + 0x9d bytes
System.Windows.Forms.dll!System.Windows.Forms.ComboBox.WmReflectCommand(ref System.Windows.Forms.Message m) + 0x13b bytes
System.Windows.Forms.dll!System.Windows.Forms.ComboBox.WndProc(ref System.Windows.Forms.Message m) + 0x8d8 bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref System.Windows.Forms.Message m) + 0x13 bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message m) + 0x31 bytes
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(System.IntPtr hWnd, int msg, System.IntPtr wparam, System.IntPtr lparam) + 0x64 bytes
[Native to Managed Transition]
[Managed to Native Transition]
System.Windows.Forms.dll!System.Windows.Forms.Control.SendMessage(int msg, System.IntPtr wparam, System.IntPtr lparam) + 0x24 bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.ReflectMessageInternal(System.IntPtr hWnd, ref System.Windows.Forms.Message m) + 0x3b bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.WmCommand(ref System.Windows.Forms.Message m) + 0x2e bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message m) + 0x387 bytes
System.Windows.Forms.dll!System.Windows.Forms.ScrollableControl.WndProc(ref System.Windows.Forms.Message m) + 0x2a bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref System.Windows.Forms.Message m) + 0x13 bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message m) + 0x31 bytes
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(System.IntPtr hWnd, int msg, System.IntPtr wparam, System.IntPtr lparam) + 0x64 bytes
[Native to Managed Transition]
[Managed to Native Transition]
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DefWndProc(ref System.Windows.Forms.Message m) + 0x6d bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.DefWndProc(ref System.Windows.Forms.Message m) + 0xc bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.WmCommand(ref System.Windows.Forms.Message m) + 0x46 bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message m) + 0x387 bytes
System.Windows.Forms.dll!System.Windows.Forms.ComboBox.WndProc(ref System.Windows.Forms.Message m) + 0x882 bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref System.Windows.Forms.Message m) + 0x13 bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message m) + 0x31 bytes
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(System.IntPtr hWnd, int msg, System.IntPtr wparam, System.IntPtr lparam) + 0x64 bytes
[Native to Managed Transition]
[Managed to Native Transition]
System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(System.IntPtr dwComponentID, int reason, int pvLoopData) + 0x287 bytes
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int reason, System.Windows.Forms.ApplicationContext context) + 0x16c bytes
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext context) + 0x61 bytes
System.Windows.Forms.dll!System.Windows.Forms.Application.Run(System.Windows.Forms.Form mainForm) + 0x31 bytes
TinyOPDS.exe!TinyOPDS.Program.Main() Line 55 + 0x8 bytes C#
[Native to Managed Transition]
[Managed to Native Transition]
mscorlib.dll!System.AppDomain.ExecuteAssembly(string assemblyFile, System.Security.Policy.Evidence assemblySecurity, string[] args) + 0x6d bytes
Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() + 0x2a bytes
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x63 bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool ignoreSyncCtx) + 0xb0 bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x2c bytes
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 bytes
[Native to Managed Transition]

Ответ написан
sensboston
@sensboston Автор вопроса
Похоже

А вот и не похоже, не привязан! :) Вот это и непонятно.

P.S. Я сегодня-завтра закоммичу код, можно будет самому проверить (если интересно, конечно).
Ответ написан
Комментировать
sensboston
@sensboston Автор вопроса
Update: все, разобрался. Дело было в default value для NumericUpDown — оно было больше минимума :D А в SettingsProvider реализовано через foreach, поэтому при обновлении любого контрола, забинденного к settings, возникала ошибка.
Ответ написан
Комментировать
@mayorovp
Думаю, что дело в отсутствии value converter для системного int

Для системного int существует value converter. Ищите в другом месте
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы