2014-02-20 4 views
1

У меня есть большинство объектов кнопки TextBlock и радио в моем приложении, связанные с моей dictionnaryсловарь Failure связывания в WPF

хранить новое значение в словаре.

Проблема в том, что отказ привязки вызывает исключение, которое происходит очень медленно.

Вот пример: (. Этот код работает правильно, это просто медленно, если он не может найти матч в стартовом приложение)

<StackPanel> 
    <TextBox Text="{Binding Dictio[0], Mode=TwoWay}"/> 
    <TextBox Text="{Binding Dictio[1], Mode=TwoWay}"/> 
    <RadioButton GroupName="select" IsChecked="{Binding Dictio[2], Mode=TwoWay}" Content="true"/> 
</stackPanel> 

И в моем классе

private Dictionary<int, object> _Dictio; 

public MainWindow() 
     { 
      Dictio = new Dictionary<int, object>(); 
      this.DataContext = this; 
      InitializeComponent(); 
     } 

public Dictionary<int, object> Dictio 
     { 
      get { return _Dictio; } 
      set { _Dictio = value; } 
     } 

private void test(object sender, RoutedEventArgs e) 
{ 
    foreach (KeyValuePair<int, object> kvp in Dictio) 
      { 
       Console.Out.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value); 
     } 
} 

Когда я пытаюсь запустить приложение и вяжущие пытается для поиска Dictio [ключ], я получаю это в моем окне вывода для все ключа моего dictionnary Dictio:

System.Windows.Data Error: 17 : Cannot get 'Item[]' value (type 'Object') from 'Dictio' (type 'Dictionary`2'). BindingExpression:Path=Dictio[4]; DataItem='MainWindow' (Name=''); target element is 'RadioButton' (Name='mm'); target property is 'IsChecked' (type 'Nullable`1') TargetInvocationException:'System.Reflection.TargetInvocationException: Une exception a été levée par la cible d'un appel. ---> System.Collections.Generic.KeyNotFoundException: La clé donnée était absente du dictionnaire. 
    à System.Collections.Generic.Dictionary`2.get_Item(TKey key) 
    --- Fin de la trace de la pile d'exception interne --- 
    à System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) 
    à System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) 
    à System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) 
    à System.Reflection.RuntimePropertyInfo.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture) 
    à MS.Internal.Data.PropertyPathWorker.GetValue(Object item, Int32 level) 
    à MS.Internal.Data.PropertyPathWorker.RawValue(Int32 k)' 

Есть ли способ, чтобы соединение не выдавало исключение, если словарь пуст

+0

Вы можете связать с помощью преобразователя, который будет проверять размер словаря перед тем возвращающ значение –

+0

вы можете объяснить больше о конвертере, как я могу разработать, если у вас есть пример – user3222970

ответ

0

Вы также можете инициализировать словарь с пустыми значениями, а затем установить обязательный режим OneWayToSource так:

public MainWindow() 
{ 
    Dictio = new Dictionary<int, object>(); 
    for (int i = 0; i < 200; i++) 
    { 
     Dictio.Add(i, new object()); 
    } 
    InitializeComponent(); 
    this.DataContext = this; 
} 

<StackPanel> 
    <TextBox Text="{Binding Dictio[0], Mode=OneWayToSource}"/> 
    <TextBox Text="{Binding Dictio[1], Mode=OneWayToSource}"/> 
</StackPanel> 
+0

Да, наконец, я добился успеха в привязке без ошибок благодаря @Miro Bucko – user3222970

0

Один из способов решения этой проблемы - переопределить Dictionary<int, object>.

public class CustomDictionary : IEnumerable 
{ 
    private Dictionary<int, Tuple<DependencyObject, DependencyProperty>> properties = new Dictionary<int, Tuple<DependencyObject, DependencyProperty>>(); 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     foreach (var item in properties) 
     { 
      yield return new KeyValuePair<int, object>(item.Key, item.Value.Item1.GetValue(item.Value.Item2)); 
     } 
    } 

    public void Add(int index, DependencyObject obj, DependencyProperty property) 
    { 
     properties.Add(index, new Tuple<DependencyObject, DependencyProperty>(obj, property)); 
    } 

    public object this[int index] 
    { 
     get 
     { 
      return properties[index].Item1.GetValue(properties[index].Item2); 
     } 
     set 
     { 
      properties[index].Item1.SetCurrentValue(properties[index].Item2, value); 
     } 
    } 
} 

Тогда вместо того, чтобы использовать словарь везде вы будете использовать CustomDictionary так:

private CustomDictionary _Dictio; 

public CustomDictionary Dictio 
{ 
    get { return _Dictio; } 
    set { _Dictio = value; } 
} 

Также в вашем MainWindow вы должны инициализировать Dictio после вызова InitializeComponent() следующим образом:

public MainWindow() 
{ 
    InitializeComponent(); 

    Dictio = new CustomDictionary(); 
    Dictio.Add(0, textBox1, TextBox.TextProperty); 
    Dictio.Add(1, textBox2, TextBox.TextProperty); 
    Dictio.Add(2, radioButton, RadioButton.IsCheckedProperty); 

    this.DataContext = this; 
} 

Это добавит экземпляр DependencyObjects и соответствующего DependencyProperty, которые вы хотите привязать, к словарю.

+0

Спасибо за ответ, но когда я хочу отображать содержимое Dictio, у меня есть пример ошибки моей функции private void test (отправитель объекта, RoutedEventArgs e) { Console.Out.WriteLine (Dictio [1]);} и у меня есть ошибка «l'exception NullReferenceException n'a pas été gérée» – user3222970

+0

Вы инициализировали Dictio, прежде чем пытались отображать его элементы? –

+0

Как я могу инициализировать Dictio, я хочу заполнить диктофон через файл xaml, как показано выше. – user3222970

0

Я использую свой класс CustomDictionary

это это мой XAML файл

<StackPanel> 
    <TextBox Name="textBox1" Text="{Binding Dictio[0], Mode=TwoWay}"/> 
    <TextBox Name="textBox2" Text="{Binding Dictio[1], Mode=TwoWay}"/> 
    <RadioButton Name="radioButton" GroupName="select" IsChecked="{Binding Dictio[2], Mode=TwoWay}" Content="true"/> 
<Button Content="test" Click="test"/> 
</StackPanel> 

в моем классе

private CustomDictionary _Dictio; 

public MainWindow() 
     { 
      Dictio = new CustomDictionary(); 
      this.DataContext = this; 
      InitializeComponent(); 
     } 

    public CustomDictionary Dictio 
      { 
       get { return _Dictio; } 
       set { _Dictio = value; } 
      } 

    private void test(object sender, RoutedEventArgs e) 
    { 
     foreach (KeyValuePair<int, object> kvp in Dictio) 
       { 
        Console.Out.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value); 
      } 
    } 

, когда я исполняю я эта ошибка

Une exception de première chance de type 'System.Collections.Generic.KeyNotFoundException' s'est produite dans mscorlib.dll 

в вашем сл задница CustomDictionnary в

return properties[index].Item1.GetValue(properties[index].Item2); 
+0

Вы забыли добавить элементы в Dictio, как я это сделал в ответ. Также вы не должны связываться в xaml. –

+0

Я хочу связывать в xaml, потому что у меня есть более 150 элементов управления, поэтому я не могу добавить весь элемент управления в код, который я хочу связать в xaml, поэтому – user3222970

+0

Можете ли вы привести пример того, как выглядит элемент управления? (xaml) –

Смежные вопросы