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

时间:2013-06-25 20:35:32

标签: c# wpf treeview

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

我以为我只是从itemcontainergenerator获取容器并在headertemplate中搜索控件。但是,我收到错误,因为未应用标头模板。

 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事件做出反应,或者大小可能没有改变。

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

编辑:一张海报暗示我这一切都错了。可能是真的,但我不知道怎么回事。

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

signalgraph有两个属性来绘制图形,signal_graph_window_width和信号图的宽度。前者是窗口具有多少实际空间,并且是根据window.actualwidth - signalnamepanel.width计算的。后者决定了实际需要绘制多少数据。

信号图包裹在一个包含在滚动查看器中的网格中,因此如果屏幕上显示的数据多于可以显示的数据,则可以滚动查看其余数据。我想将scrollviewer仅放在包含signalgraph的网格部分上,以便在滚动时信号名保持可见。

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

当我有一个itemcollection时,这一切都运行正常,但后来我决定使用treeview,所以我可以扩展实际的信号。不幸的是,抓取模板化itemcontrol的代码隐藏修改不再适用于新的树视图模板。

现在我的想法是解决方法是弄清楚如何访问这里定义的正确控件:

<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修改图形宽度的原因是因为当用户调整窗口大小超出信号的绘制长度时,我想重绘信号并将其扩展到窗口的末尾。

从这里可以看出,当我调整大小时,信号不会被重绘到屏幕的末尾。我应该如何让signalgraph知道需要绘制更多信息才能到达屏幕的末尾?

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

我有一个viewmodel

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

    SignalData signal_data;
采用signaldata和signaldata的

包含一个可观察的信号集合:

 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方法,只是手动创建扩展按钮。我认为学习使用库是正确的方法,但最终我认为我的真正问题是,为什么不滚动查看器更新内部控件的大小。是否有合适的解决方案来制作自定义滚动条,以便在调整大小时更新其内容?

1 个答案:

答案 0 :(得分:0)

所以我终于想出了如何避免手动调用子项中的控件,而男孩的代码看起来更干净。基本上问题是我需要覆盖MeasureOverride for frameworkelement以及更改绑定属性以获得affectmeasure元数据选项。

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));

通过正确地覆盖度量,frameworkelement的大小会更新,因此我可以在frameworkelement上附加一个事件处理程序来强制重绘以强制重绘。