2012-04-15 15 views
4

DataGridにはCellTemplateCellEditingTemplateを使用します。両方のDataTemplatesではTextBlockが表示されてもFalseが返されますが、とFocus()が返され、Trueが返されます。TextBox.IsLoadedは、表示後にFalseを返します

これはバグですか?あるいは、誰かが説明することができます、この行動の理由は何ですか?


私は、デモの目的のために、このサンプルアプリケーションを作成しました。

MainWindow.xaml.cs

namespace WpfApplication 
{ 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 

      this.DataContext = new List<string> { "Row1", "Row2" }; 
     } 
    } 

    public class FocusAttached 
    { 
     public static bool GetIsFocused(DependencyObject obj) 
     { 
      return (bool)obj.GetValue(IsFocusedProperty); 
     } 

     public static void SetIsFocused(DependencyObject obj, bool value) 
     { 
      obj.SetValue(IsFocusedProperty, value); 
     } 

     public static readonly DependencyProperty IsFocusedProperty = 
      DependencyProperty.RegisterAttached("IsFocused", typeof(bool), typeof(MainWindow), new UIPropertyMetadata(false, IsFocusedChanged)); 

     static void IsFocusedChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
     { 
      FrameworkElement element = obj as FrameworkElement; 

      if ((bool)e.NewValue) 
      { 
       Console.Write(element); 
       Console.Write(" IsLoaded=" + element.IsLoaded); 
       Console.Write(" IsVisible=" + element.IsVisible); 
       Console.Write(" Focusable=" + element.Focusable); 
       // here I call Focus() 
       Console.Write(" Focus() returns:" + element.Focus()); 
       Console.WriteLine(" IsLoaded=" + element.IsLoaded); 
      } 
     } 
    } 
} 

MainWindow.xaml

<Window x:Class="WpfApplication.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:c="clr-namespace:WpfApplication" 
     Title="Please click on row!" SizeToContent="WidthAndHeight"> 
    <DataGrid ItemsSource="{Binding}" AutoGenerateColumns="False"> 
     <DataGrid.Columns> 
      <DataGridTemplateColumn> 
       <DataGridTemplateColumn.CellTemplate> 
        <DataTemplate> 
         <TextBlock Text="{Binding IsLoaded, RelativeSource={RelativeSource Self}, Mode=OneWay, 
                StringFormat='TextBlock in CellTemplate: IsLoaded={0}'}" /> 
        </DataTemplate> 
       </DataGridTemplateColumn.CellTemplate> 

       <DataGridTemplateColumn.CellEditingTemplate> 
        <DataTemplate> 
         <TextBox c:FocusAttached.IsFocused="True" 
           Text="{Binding IsLoaded, RelativeSource={RelativeSource Self}, Mode=OneWay, 
               StringFormat='Even after call Focus(): IsLoaded={0}'}" />          
        </DataTemplate> 
       </DataGridTemplateColumn.CellEditingTemplate> 
      </DataGridTemplateColumn> 
     </DataGrid.Columns> 

     <DataGrid.CellStyle> 
      <Style TargetType="DataGridCell"> 
       <Setter Property="Focusable" Value="False" /> 
       <Style.Triggers> 
        <Trigger Property="IsSelected" Value="True"> 
         <Setter Property="IsEditing" Value="True" /> 
        </Trigger> 
       </Style.Triggers> 
      </Style>    
     </DataGrid.CellStyle> 
    </DataGrid> 
</Window> 

答えて

1

まずIsLoadedは、依存関係プロパティではありませんので、あなたのバインディングは、役に立ちません。通知はありません。テキストの変更はありません。

IsLoadedは測定と配置のように延期されているため、falseです。要素はフォーカス可能で、可視であり、有効になっているので、フォーカスを合わせることができます。しかし、この時点で要素がすでに測定されレンダリングされているという保証はありません。これらのアクションはDispatcherにエンキューされます。それらが処理されると、IsLoadedがtrueになります。これを試してください:

static void IsFocusedChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
{ 
    FrameworkElement element = obj as FrameworkElement; 

    if ((bool)e.NewValue) 
    { 
     Console.Write(element); 
     Console.Write(" IsLoaded=" + element.IsLoaded); 
     Console.Write(" IsVisible=" + element.IsVisible); 
     Console.Write(" Focusable=" + element.Focusable); 
     // here I call Focus() 
     Console.Write(" Focus() returns:" + element.Focus()); 
     element.Dispatcher.BeginInvoke((Action)(() => 
      { 
       Console.WriteLine(" IsLoaded=" + element.IsLoaded); 
      }), 
      System.Windows.Threading.DispatcherPriority.Loaded); 
    } 
} 
+0

はい、IsLoadedはTrueで、あなたの権利はBindingです。しかし、これは、まだプレゼンテーションエンジンに統合されていない(または決して決してない)場合でも、要素をフォーカスすることができることを意味します( 'IsLoaded = True')?そして 'IsVisible = True'は要素を本当に見ることができるという意味ではありませんか? – LPL

+0

ここで問題となるのは、異なるプロセスをさまざまな性質で比較しようとしていることです。 IsLoadedは、計測/配置/レンダリングのメカニズムの一部であり、フォーカスはアプリケーションロジックの一部です。要素はフォーカスに有効ですか?はい、それは有効で可視であるためです(テンプレートが実現されたため)PresentationSourceに添付されています。要素は既に読み込まれていますか?まだありませんが、それはPresentationSourceに添付されているためです。 –

関連する問題