简体   繁体   English

WPF中的词典失败绑定

[英]Dictionary Failure binding in WPF

I have most of the textblock and radio button objects in my app bound to my dictionnary 我的应用程序中的大部分textblock和单选按钮对象都绑定到字典上

I store the new value in a Dictionary. 我将新值存储在字典中。

The problem is that the binding failure is throwing an exception that is very slow. 问题是绑定失败引发了非常缓慢的异常。

Here is an example: (this code runs correctly, it is just slow if it can't find a match in the start app.) 这是一个示例:(此代码正确运行,如果在启动应用中找不到匹配项,则速度很慢。)

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

And in my class 在我班上

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

When I try to start app and the binding tries to lookup Dictio[key], I get this in my output window for all the key of my dictionnary Dictio: 当我尝试启动应用程序并且绑定尝试查找Dictio [key]时,我在输出窗口中得到了字典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)'

Is there a way to make the connection not throw an exception if the dictionary is empty 如果字典为空,是否有一种方法可以使连接不引发异常

One way to solve this is to override the Dictionary<int, object> . 解决此问题的一种方法是重写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);
        }
    }
}

Then instead of using Dictionary everywhere you would use CustomDictionary like so: 然后,不要像在任何地方都使用Dictionary那样使用CustomDictionary:

private CustomDictionary _Dictio;

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

Also in your MainWindow you have to initialize the Dictio AFTER you call InitializeComponent() like so: 同样在您的MainWindow中,您必须在调用InitializeComponent()之后初始化Dictio,如下所示:

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

This will add the instance of the DependencyObjects and the corresponding DependencyProperty, that you want to bind to, to the dictionary. 这会将DependencyObjects的实例以及要绑定到的相应DependencyProperty添加到字典中。

I use your class CustomDictionary 我使用您的班级CustomDictionary

this's my xaml file 这是我的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>

in my class 在我班上

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

when i execute i have this error 当我执行我有这个错误

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

in your class CustomDictionnary in 在您的类CustomDictionnary中

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

You can also initialize the dictionary with empty values and then set binding mode to OneWayToSource like this: 您还可以使用空值初始化字典,然后将绑定模式设置为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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM