4

私はとDataGridを使用CellTemplateCellEditingTemplateます。両方のDataTemplatesで、 FrameworkElement.IsLoadedプロパティFalseは、が表示されていてもTextBlock、を使用しTextBoxFocus()呼び出しが返されTrueます。

これはバグですか?または誰かが説明できますか、この動作の理由は何ですか?


このサンプルアプリケーションは、デモンストレーション用に作成しました。

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

1 に答える 1

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);
    }
}
于 2012-04-16T09:40:14.047 に答える