如何在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方法和手动创建展开按钮是否不是更好。我认为学习使用库是正确的方法,但最终我认为我的真正问题是,为什么滚动查看器不更新内部控件的大小。制作一个自定义滚动条,在调整大小时更新其内容,这是正确的解决方案吗?
所以我终于找到了如何避免手动调用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,以强制重新绘制。