如何在sizechanged事件中更新由itemtemplate生成的树视图项

本文关键字:视图 itemtemplate sizechanged 事件 更新 | 更新日期: 2023-09-27 18:19:48

如何在包含控件的sizechanged事件上更新由项模板生成的树视图项?

我想我应该从itemcontainergenerator中获取容器,然后在头模板中搜索控件。但是,我得到了一个错误,因为没有应用头模板。

 private void SignalBox_SizeChanged(object sender, SizeChangedEventArgs e)
    {
      if (e.WidthChanged)
      {
        double change_in_width = e.NewSize.Width - e.PreviousSize.Width;
        signal_graph_window_width = ActualWidth - NamePanelWidth;
        TreeView tv = this.signal_treeview_item_control;
        foreach (var item in tv.Items)
        {
          TreeViewItem container = tv.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;
          if (container != null && container.HeaderTemplate.Is)
          {
            SignalGraph sg = container.HeaderTemplate.FindName("signal_graph", container) as SignalGraph;

我阅读了更多关于这个主题的内容,似乎我遇到的错误是因为模板尚未应用。我读到的大多数答案都建议将事件处理程序绑定到onapplytemplate,但我不能只对onapplytemplate事件做出反应,或者大小可能没有改变。

我希望我的信号图能够根据可用的大小进行绘制,并在窗口大小变化时重新绘制和更新。

编辑:一张海报表明我做这件事完全错了。也许是真的,但我不知道该怎么办。

我有一个自定义用户控件"signal_box",还有一个绑定到signal_box的子FrameworkElement信号图的属性"signal_graph_window_width"。

signalgraph使用两个属性来绘制图,signal_graph_window_width和signalgrap的宽度。前者是窗口的实际空间,由window.actualwidth-signalnamepanel.width计算得出。后者决定实际需要绘制多少数据。

信号图被包裹在一个网格中,这个网格被包裹在滚动查看器中,这样,如果屏幕上显示的数据超过了可以显示的数据,你就可以滚动查看其余的数据。我想把滚动查看器只放在包含信号图的网格部分,这样当你滚动时,信号名就可以保持可见。

最初我有信号盒手动修改信号图的大小。这是在codeehind中完成的,通过在ItemsControl的itemtemplate中找到具有正确名称的控件来更新信号图的宽度。

当我有一个项目集合时,这一切都很好,但后来我决定使用树视图,这样我就可以扩展实际的信号。不幸的是,获取模板化项目控件的codeehind修改不再适用于新的树视图模板。

现在,在我看来,解决方案就是找出如何访问此处定义的正确控件:

<TreeView.ItemTemplate>
    <HierarchicalDataTemplate ItemsSource ="{Binding Path = bits}">
      <Grid x:Name="signal_box_grid" Background="Black">
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="200"/>
          <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <wpfExp:SignalNamePanel Grid.Column="0"
            Height="{Binding ElementName=signal_box, Path=GraphHeight, Mode=OneWay}"
            x:Name="signal_name_panel"
            MainText="{Binding Path = SignalName}" 
          />
        <wpfExp:SignalGraph Grid.Column="1"
            x:Name="signal_graph"
            IsSignal="True"
            Height="{Binding ElementName=signal_box, Path=GraphHeight, Mode=OneWay}"
            PenWidth="{Binding ElementName=signal_box, Path=GraphPenWidth, Mode=OneWay}"
            Signal="{Binding}" 
            signal_graph_window_width="{Binding ElementName=signal_box, Path=signal_graph_window_width, Mode=OneWay}"
            X_Scale="{Binding ElementName=signal_box, Path=X_Scale, Mode=OneWay}"
            MaxTimeValue="{Binding RelativeSource = {RelativeSource AncestorType={x:Type wpfExp:SignalBox}}, Path = _SignalData.MaxTimeValue}"
          />
      </Grid>

      <HierarchicalDataTemplate.ItemTemplate>
            <DataTemplate>
              <Grid Background="Black">
                <Grid.ColumnDefinitions>
                  <ColumnDefinition Width="200"/>
                  <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <wpfExp:SignalNamePanel Grid.Column="0"
                Height="{Binding ElementName=signal_box, Path=GraphHeight, Mode=OneWay}"
                x:Name="signal_name_panel"
                MainText="{Binding Path = BitNumber}" 
              />
                <wpfExp:SignalGraph Grid.Column="1"
                x:Name="signal_graph"
                IsSignal="False"
                Height="{Binding ElementName=signal_box, Path=GraphHeight, Mode=OneWay}"
                PenWidth="{Binding ElementName=signal_box, Path=GraphPenWidth, Mode=OneWay}"
                Bit="{Binding}" 
                signal_graph_window_width="{Binding ElementName=signal_box, Path=signal_graph_window_width, Mode=OneWay}"
                X_Scale="{Binding ElementName=signal_box, Path=X_Scale, Mode=OneWay}"
                MaxTimeValue="{Binding RelativeSource = {RelativeSource AncestorType={x:Type wpfExp:SignalBox}}, Path = _SignalData.MaxTimeValue}"
              />
              </Grid>
            </DataTemplate>
          </HierarchicalDataTemplate.ItemTemplate>
        </HierarchicalDataTemplate>
      </TreeView.ItemTemplate>

但也许我只是做错了。

我之所以想根据Sizechanged修改图形的宽度,是因为当用户将窗口的大小调整到信号的绘制长度之外时,我想重新绘制信号并将其扩展到窗口的末尾。

从这里可以看出,当我调整大小时,信号并没有被重新绘制到屏幕的末尾。我应该如何让信号图知道它需要画更多才能到达屏幕的尽头?

http://picpaste.com/signalgraph2-oObkPXLX.JPG

我有一个视图模型

   public class SignalDataViewModel
  {
    ObservableCollection<SignalViewModel> _signals;
    public ObservableCollection<SignalViewModel> Signals
    {
      get
      {
        return _signals;
      }
      private set
      {
        _signals = value;
      }
    }
    SignalData signal_data;

它获取信号数据,信号数据包含可观察的信号集合:

 public ObservableCollection<Signal> list_of_signals
    {
      get;
      set;
    }

它看起来像这样:

public class Signal
  {
    public bool isBus
    {
      get;
      private set;
    }
    public List<KeyValuePair<int, IList<byte>>> SignalValues
    {
      get;
      private set;
    }
    public List<KeyValuePair<int, string>> HexSignalValues
    {
      get;
      private set;
    }
    public string SignalName
    {
      get;
      private set;
    }
    public Signal(string name, bool isBus)
    {
      SignalValues = new List<KeyValuePair<int, IList<byte>>>();
      this.SignalName = name;
      this.isBus = isBus;
    }

我一直在想,仅仅使用我以前使用的itemscontrol方法和手动创建展开按钮是否不是更好。我认为学习使用库是正确的方法,但最终我认为我的真正问题是,为什么滚动查看器不更新内部控件的大小。制作一个自定义滚动条,在调整大小时更新其内容,这是正确的解决方案吗?

如何在sizechanged事件中更新由itemtemplate生成的树视图项

所以我终于找到了如何避免手动调用children中的控件,男孩让代码看起来更干净。基本上,问题是我需要为我的frameworkelement重写MeasureOverride,并更改绑定属性以具有affectsmeasure元数据选项。

public double signal_graph_window_width
    {
      get { return (double)GetValue(signal_graph_window_width_property); }
      set
      {
        SetValue(signal_graph_window_width_property, value);
      }
    }
    public static readonly DependencyProperty signal_graph_window_width_property =
      DependencyProperty.Register("signal_graph_window_width",
      typeof(double), typeof(SignalGraph),
      new FrameworkPropertyMetadata(new double(), FrameworkPropertyMetadataOptions.AffectsMeasure));

通过正确地重写measure,frameworkelement的大小会得到更新,因此我可以在frameworkelement上将事件处理程序附加到sizechanged,以强制重新绘制。