2

アプリ内のほとんどのLabelオブジェクトは、Web サービスから置き換えることができるようにバインドされています。

置換を Dictionary に保存します。置換は、アプリ用にロードされたクライアントによって異なります。

私が抱えている問題は、ほとんどの場合、ラベルを置き換えないことと、バインディングの失敗によって非常に遅い例外がスローされることです。

次に例を示します: (このコードは正しく機能することに注意してください。一致するものが見つからない場合は処理が遅くなります。)

<Label Content="_Gender"
       Helpers:CaptionHelper.PropertyName="Content"
       Helpers:CaptionHelper.PropertyValue="{Binding Labels[Gender], 
                                                     FallbackValue=_Gender}"
       Target="{Binding ElementName=cbGender}" />

バインディングが Labels[Gender] を検索しようとすると、出力ウィンドウに次のように表示されます。

System.Windows.Data Warning: 17 : Cannot get 'Item[]' value (type 'String') from 'Labels' (type 'Dictionary`2'). BindingExpression:Path=Labels[Gender]; DataItem='MyViewMV'
      (HashCode=63776763); target element is 'Label' (Name=''); target property is 'PropertyValue'(type 'String') TargetInvocationException:'System.Reflection.TargetInvocationException: 
           Exception has been thrown by the target of an invocation. ---> System.Collections.Generic.KeyNotFoundException: 
           The given key was not present in the dictionary.
   at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle._InvokeMethodFast(Params Truncated)
   at System.Reflection.RuntimeMethodInfo.Invoke(Params Truncated)
   at System.Reflection.RuntimeMethodInfo.Invoke(Params Truncated)
   at MS.Internal.Data.PropertyPathWorker.GetValue(Params Truncated)
   at MS.Internal.Data.PropertyPathWorker.RawValue(Params Truncated)'

私はこれらをたくさん持っているので、それらすべてを実行するのに約 1 秒かかります。

辞書検索が失敗したときにバインディングが例外をスローしないようにする方法はありますか? それともどういうわけか早く失敗しますか?

4

3 に答える 3

3

オプションがある場合は、IDictionary実装をreturn してnull代わりに使用するものに変更しますTargetNullValue(または、まだ使用している場合はbe IDictionary<TKey, object>and return ):DependencyProperty.UnsetValueFallbackValue

public class PassthruDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
    private Dictionary<TKey, TValue> instance;

    // ... other stuff

    public TValue this[TKey key]
    {
        get
        {
            TValue value;
            if (instance.TryGetValue(key, out value))
            {
                return value;
            }
            else
            {
                return default(TValue);
            }
        }
        // ... more
    }
}
于 2012-11-28T17:29:43.517 に答える
1

はい、デバッガーでコードを実行しないと、速度が大幅に向上する可能性があります。実際、Visual Studio でのスタックティースの印刷は、最も遅い部分です。デバッガーを接続せずにアプリケーションを実行すると、パフォーマンスの低下はもはや目立たなくなると確信しています。

ライブラリ内で例外をキャッチするという同様の問題がありましたが、その場合でも、例外がキャッチされる (および処理される) たびに、コードでキャッチされた最初のチャンスの例外に関するメモが VS によって出力されます。起動時に例外が約 50 回トリガーされ、アプリケーションの起動に 10 秒ほどかかりましたが、これはすべてコンソール ログが原因でした。デバッガーなしでアプリケーションを実行すると、ほぼ瞬時に起動しました。

したがって、その例外を回避しようとすることは、時期尚早の最適化にすぎない可能性があります。

于 2012-11-28T16:53:12.017 に答える
1

編集:

実際には、VS 出力ペインで出力を無効にするだけです。実際にはスピードアップしません。

オリジナル:

同様の問題がありましたが、エラーをキャッチしてログに記録したかったのです。ただし、次のソリューションを使用して、VS2010 出力ウィンドウへのエラーの出力を単に無効にすることができます。ソリューションは 2 つの部分に分かれています。最初の部分は単純なクラスです。

using System.Diagnostics;

namespace DevBindingErrors
{
    /// <summary>
    /// Intercepts all binding error messages. Stops output appearing in VS2010 debug window.
    /// </summary>
    class BindingTraceListener: TraceListener
    {
        private string _messageType;

        public override void Write(string message)
        {
            // Always happens in 2 stages: first stage writes "System.Windows.Data Error: 40 :" or similar.
            _messageType = message;
        }

        public override void WriteLine(string message)
        {
            Debug.WriteLine(string.Format("{0}{1}", _messageType, message));
        }
    }
}

2 番目の部分は App.xaml.cs にあります。

using System.Diagnostics;
using System.Windows;

namespace DevBindingErrors
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        public App()
        {
            PresentationTraceSources.Refresh();
            PresentationTraceSources.DataBindingSource.Listeners.Add(new BindingTraceListener());
            PresentationTraceSources.DataBindingSource.Switch.Level = SourceLevels.Warning;
        }
    }
}

すべてのバインド エラーを無視する場合は、そのDebug.WriteLine(...)行をコメント アウトします。(これはあまりお勧めしませんが) これにより、アプリケーションのデバッグ機能を失うことなく、実行も高速化されます。

このソリューションのアイデアは、このページから生まれました。このページには、WPF のトレース ソースの詳細も記載されています。

于 2012-11-28T17:20:41.050 に答える