2011-07-07 29 views
2

私はしばらくの間これを苦労しています。私は自分のアプリケーションにMaster/Detailsレイアウトを持っていて、他の多くのように、DataGridが無効にしたときにその選択を失うという問題に直面しています。 Essencialyは、リストから要素を選択して一連のフィールドを設定した後、「編集」を押すと、DataGridが無効になり、すべてのフォームのフィールドが有効になります。 「保存」ボタンを押すと、データを保存した後にこれらのアクションが元に戻ります。私は、私が試してみました何の.NET Framework 4にVS 2010でWPF DataGrid - 無効にすると選択を保持する

を研究開発をWindows 7で午前


1)this postに基づいて、私は2009年6月版でのDataGridを使用しようとしましたWPF Toolkit、しかし私は同じ反応を持っていました。
2)this WPF CodePlex bug reportに基づいて、私はDataGridに基づいてカスタムコントロールを作成し、 "UnselectAllCells"への呼び出しを削除するためにOnIsEnabledChanged呼び出しをオーバーライドしようとしましたが、コード例がなくても、一度。私が試してみました:

public class FormMainDataGrid : DataGrid 
{ 
    static FormMainDataGrid() 
    { 
     IsEnabledProperty.OverrideMetadata(typeof(FormMainDataGrid), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnIsEnabledChanged))); 
    } 

    public FormMainDataGrid() : base() { } 

    private static void OnIsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     d.CoerceValue(CanUserAddRowsProperty); 
     d.CoerceValue(CanUserDeleteRowsProperty); 

     //this was added in new version !!! 
     /* 
     if (!(bool)(e.NewValue)) 
     { 
      ((DataGrid)d).UnselectAllCells(); 
     } 
     */ 

     // Many commands use IsEnabled to determine if they are enabled or not 
     CommandManager.InvalidateRequerySuggested(); 
    } 
} 

が、これはまだのようにすぐに私はデータグリッドを無効にすると、現在選択されている行を選択解除します。私はこのような(CodePlexにバグレポートの)最後のコメントをinterpreteしようとしている:

public class FormMainDataGrid : DataGrid 
{ 
    static FormMainDataGrid() 
    { 

    } 

    public static void OverrideStuff() 
    { 
     IsEnabledProperty.OverrideMetadata(typeof(FormMainDataGrid), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnIsEnabledChanged))); 
    } 

    public FormMainDataGrid() : base() { } 

    private static void OnIsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     d.CoerceValue(CanUserAddRowsProperty); 
     d.CoerceValue(CanUserDeleteRowsProperty); 

     //this was added in new version !!! 
     /* 
     if (!(bool)(e.NewValue)) 
     { 
      ((DataGrid)d).UnselectAllCells(); 
     } 
     */ 

     // Many commands use IsEnabled to determine if they are enabled or not 
     CommandManager.InvalidateRequerySuggested(); 
    } 
} 

public partial class App : Application 
{ 
    protected override void OnStartup(StartupEventArgs e) 
    { 
     FormMainDataGrid.OverrideStuff(); 
     base.OnStartup(e); 
    } 
} 

それはさえ方法の修正バージョンを発生しません。

まず、私はこれのために正しい道を進んでいますか? Deselectionがこのメソッドによって引き起こされたことを考慮して、自分のメソッドのために内部コールを 'OnIsEnabledChanged'に完全に置き換えることはできますか? この問題に取り組むことができる別の方法はありますか? さらに具体的には、オーバーライドではないので、このメソッドのベースバージョンへの呼び出しを停止するにはどうすればいいですか?つまり、base.OnIsEnabledChangedを呼び出すことはできませんか?

ありがとう!

答えて

0

IsHitTestVisible = falseの場合、Up-Downキーと同じ問題が存在します。 SelectedValueのを変更すると、コントロールが無効になりますが、あるときので、私はただ気をつけなければならない...これはかなりうまく機能

public class FormMainDataGrid : DataGrid 
    { 
     public FormMainDataGrid() : base() { 
      this.IsEnabledChanged += new DependencyPropertyChangedEventHandler(DataGrid_IsEnabledChanged); 
      this.SelectionChanged += new SelectionChangedEventHandler(DataGrid_SelectionChanged); 
     } 

     private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs args) 
     { 
      if (this.IsEnabled) 
      { 
       _selectedValue = this.SelectedValue; 
      } 
     } 

     private object _selectedValue; 

     private void DataGrid_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs args) 
     { 
      this.Dispatcher.BeginInvoke((Action)(() => 
      { 
       this.SelectedValue = _selectedValue; 
      }), null); 
     } 
    } 

だから私はこのようなカスタムコントロールを再取り組んでいるやってしまったものを...

結論として、私はあなたの解決策が最も完全だと信じていますが、私のフォームのコードをできるだけリーンの&とすることができます。

ありがとうございました!

1

私は一般的にこのような理由でコントロールを無効にしません。私は、データバインディングの電流を維持するコントロールを崩壊させる方がはるかに優れているか、見た目を維持しなければならないが、何らかの相互作用を許さなければ、通常は倒壊してコマンド上で見えるように、

+0

たTHX戦士。オーバーレイの問題は、DataGrid Focusable = False、AllowKeyboardFocus = Falseを設定しても、ユーザーは選択したままで遊ぶことができるということです(何らかの理由でフォーカスを次のDataGridにヒットし、実際にスクロールを開始するまでコントロールします)。行の詳細パターンはもっと奨励されていますが、私はUIデザイナーではないので、このようなデザインの制限は本当にデザイナーを幸せにしません! ;-) – JFTxJ

+0

IsHitTestVisible = Falseに設定してみてください。ユーザーはそれに影響を与えてはなりません。 – CodeWarrior

3

今後の参考として、誰かが同じ問題を抱えている場合。
SelectedValueを再設定すると、多くの副作用が発生します。この記事で言及した問題のみをインストールせずに4.5 4.0のインストール中に起こること

public class MyDataGrid : DataGrid 
{ 
    static MyDataGrid() 
    { 
     IsEnabledProperty.OverrideMetadata(typeof(MyDataGrid), new CustomFrameworkPropertyMetadata(OnIsEnabledChanged)); 
    } 

    /// <summary> 
    /// Fixes the issue that the DataGrid's selection is cleared whenever the DataGrid is disabled. 
    /// Tricky: this issue only happens for 4.0 installations, it is fixed in 4.5 (in-place upgrade) installations. 
    /// </summary> 
    /// <param name="d"></param> 
    /// <param name="e"></param> 
    private static void OnIsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     d.CoerceValue(CanUserAddRowsProperty); 
     d.CoerceValue(CanUserDeleteRowsProperty); 

     //this is there in 4.0 dlls, not in the in-place upgrade 4.5 dlls. 
     //if (!(bool)(e.NewValue)) 
     //{ 
     // ((DataGrid)d).UnselectAllCells(); 
     //} 

     CommandManager.InvalidateRequerySuggested(); 
    } 

    class CustomFrameworkPropertyMetadata : FrameworkPropertyMetadata 
    { 
     public CustomFrameworkPropertyMetadata(PropertyChangedCallback propertyChangedCallback) 
      : base(propertyChangedCallback) 
     { 
     } 

     protected override void Merge(PropertyMetadata baseMetadata, DependencyProperty dp) 
     { 
      // See: http://msdn.microsoft.com/en-us/library/system.windows.propertymetadata.merge.aspx 
      // See: http://msdn.microsoft.com/en-us/library/ms751554.aspx 
      // By default, PropertyChangedCallbacks are merged from all owners in the inheritance hierarchy, 
      // so all callbacks are called whenever the property changes. 
      var thisPropertyChangedCallback = this.PropertyChangedCallback; 

      base.Merge(baseMetadata, dp); 

      // We do NOT want that default behavior here; 
      // The callback of DataGrid should not be called here - it clears the selection, we don't want that. 
      // But the callback of UIElement should be called here - it visually disabled the element, we still want that. 
      if (baseMetadata.PropertyChangedCallback != null) 
      { 
       Delegate[] invocationList = baseMetadata.PropertyChangedCallback.GetInvocationList(); 
       PropertyChangedCallback inheritedPropertyChangedCallback = null; 
       foreach (var invocation in invocationList) 
       { 
        if (invocation.Method.DeclaringType == typeof(DataGrid)) 
        { 
         // Do nothing; don't want the callback from DataGrid that clears the selection. 
        } 
        else 
        { 
         inheritedPropertyChangedCallback = inheritedPropertyChangedCallback == null 
          ? (PropertyChangedCallback)invocation 
          : (PropertyChangedCallback)Delegate.Combine(inheritedPropertyChangedCallback, invocation); 
        } 

       } 
       this.PropertyChangedCallback = thisPropertyChangedCallback != null 
                ? (PropertyChangedCallback)Delegate.Combine(inheritedPropertyChangedCallback, thisPropertyChangedCallback) 
                : inheritedPropertyChangedCallback; 
      } 
     } 
    } 
} 



注:
これは、グリッド上のメタデータを上書きするための正しい方法です。
4.0 をターゲットとするアプリケーション(「4.5はin-place upgrade」シナリオ/ misery)であっても、.net 4.5では '固定'です。

よろしく、
公園

関連する問題