1

次のデータグリッドがあります。

<DataGrid x:Name="myDataGrid"
          RowHeaderWidth="{Binding RelativeSource={RelativeSource Self},
                           Path=RowHeight}">
  <DataGrid.Columns>
    <DataGridTextColumn Header="Name" Width="*"
                        Binding="{Binding Name}"/>
    <DataGridTextColumn Header="Age" Width="1.2*"
                        Binding="{Binding Age}"/>
  </DataGrid.Columns>
</DataGrid>

<Button Grid.Row="1" Content="Add" Click="Button_Click"
        Width="100"/>

private void Button_Click(object sender, RoutedEventArgs e)
{
  var person = new Person()
  {
    Name = "Aaa",
    Age = 27
  };
  myDataGrid.Items.Add(person);
}

public class Person
{
  public string Name { get; set; }
  public int Age { get; set; }
}

問題は、新しい行が追加されたときに水平スクロールバーが表示されることです。これは不要です。RowHeaderWidth プロパティを削除すると問題は解決しますが、検証エラーを表示するにはこれが必要です。RowHeaderWidth を固定値に設定しても役に立ちません。誰かが親切に私に解決策を提案できますか?

4

3 に答える 3

0

私が見つけた 1 つの回避策は、行と列の交点 (データグリッドの左上) にあるボタンの幅を設定することです。このボタンは、最初の行がデータグリッドに追加されると、ビジュアル ツリーに表示されます。このボタンについてはこちらで学びました

public MainWindow()
{
  InitializeComponent();
  myDataGrid.ItemContainerGenerator.StatusChanged += onItemContainerGeneratorStatusChanged;
}

private void onItemContainerGeneratorStatusChanged(object sender, EventArgs e)
{
  if (((ItemContainerGenerator)sender).Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated)
  {
    Button btn = GetVisualChild<Button>(myDataGrid);
    if (btn != null)
    {
      btn.Width = myDataGrid.RowHeaderActualWidth;
    }
  }
}

public T GetVisualChild<T>(Visual parent) where T : Visual
{
  T child = default(T);
  int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
  for (int i = 0; i < numVisuals; i++)
  {
    Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
    child = v as T;
    if (child == null) child = GetVisualChild<T>(v);
    if (child != null) break;
  }
  return child;
}

ただし、新しく追加された行に DataGrid.RowDetailsTemplate と DataGrid.SelectedItem を設定すると機能しませんでした。だから私は次のことを試しました:

private void onItemContainerGeneratorStatusChanged(object sender, EventArgs e)
{
  if (((ItemContainerGenerator)sender).Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated)
  {
    ScrollViewer sv = GetVisualChild<ScrollViewer>(myDataGrid);
    if (sv != null)
    {
      AutomationPeer automationPeer = FrameworkElementAutomationPeer.FromElement(sv);
      if (automationPeer == null)
        automationPeer = FrameworkElementAutomationPeer.CreatePeerForElement(sv);
      IScrollProvider provider = automationPeer.GetPattern(PatternInterface.Scroll) as IScrollProvider;
      try { provider.Scroll(ScrollAmount.SmallIncrement, ScrollAmount.NoAmount); }
      catch { }
      try { provider.Scroll(ScrollAmount.SmallDecrement, ScrollAmount.NoAmount); }
      catch { }
    }
  }
}

元の問題は解決されますが、新しい問題が発生します。検証エラーの赤いボックスは、エラーを示すテキスト ボックスから移動しました。

于 2013-01-30T11:23:19.053 に答える
0

私に役立つ別の回避策は次のとおりです。

private void fixScrollBarBug()
{
  ScrollBar scrollBar = GetChildByName<ScrollBar>(myDataGrid, "PART_HorizontalScrollBar");
  if (scrollBar != null)
  {
    if (VisualTreeHelper.GetChildrenCount(scrollBar) > 0)
    {
      Grid grid = (Grid)VisualTreeHelper.GetChild(scrollBar, 0);
      if (VisualTreeHelper.GetChildrenCount(grid) == 3)
      {
        try
        {
          RepeatButton leftButton = (RepeatButton)VisualTreeHelper.GetChild(grid, 0);
          RepeatButton rightButton = (RepeatButton)VisualTreeHelper.GetChild(grid, 2);

          AutomationPeer automationPeer = FrameworkElementAutomationPeer.FromElement(rightButton);
          if (automationPeer == null)
            automationPeer = FrameworkElementAutomationPeer.CreatePeerForElement(rightButton);
          IInvokeProvider provider = automationPeer.GetPattern(PatternInterface.Invoke) as IInvokeProvider;
          provider.Invoke();

          automationPeer = FrameworkElementAutomationPeer.FromElement(leftButton);
          if (automationPeer == null)
            automationPeer = FrameworkElementAutomationPeer.CreatePeerForElement(leftButton);
          provider = automationPeer.GetPattern(PatternInterface.Invoke) as IInvokeProvider;
          provider.Invoke();
        }
        catch { }
      }
    }
  }
}

最初の行が追加された後に上記のメソッドを呼び出すと、問題が解決しました。

myDataGrid.Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(
delegate
{
  fixScrollBarBug();
}));
于 2013-01-31T09:43:13.077 に答える
0

これを試して:

        <DataGrid x:Name="myDataGrid"
      RowHeaderWidth="{Binding RelativeSource={RelativeSource Self},
                       Path=RowHeight}" ScrollViewer.CanContentScroll="False" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Width="*" 
                    Binding="{Binding Name}"/>
                <DataGridTextColumn Header="Age" Width="*"
                    Binding="{Binding Age}"/>
            </DataGrid.Columns>
        </DataGrid>
于 2013-01-30T06:46:23.820 に答える