Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/285.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 更改样式时WPF列表框在SelectedItem上保留视图_C#_Wpf_Listbox_Styles - Fatal编程技术网

C# 更改样式时WPF列表框在SelectedItem上保留视图

C# 更改样式时WPF列表框在SelectedItem上保留视图,c#,wpf,listbox,styles,C#,Wpf,Listbox,Styles,我有一个列表框,点击特定按钮后,其样式和ItemTemplate会在代码中更改 listbox.ItemTemplate = FindResource("dataTemplateView1") as DataTemplate; listbox.Style = FindResource("listBoxStyle1") as Style; 有三种可能的视图,因此有三组数据模板和样式。DataTemplate包含一些文本和缩略图(每组大小不同)。这些样式只是将ItemsPanelTemplate更

我有一个列表框,点击特定按钮后,其样式和ItemTemplate会在代码中更改

listbox.ItemTemplate = FindResource("dataTemplateView1") as DataTemplate;
listbox.Style = FindResource("listBoxStyle1") as Style;
有三种可能的视图,因此有三组数据模板和样式。DataTemplate包含一些文本和缩略图(每组大小不同)。这些样式只是将ItemsPanelTemplate更改为WrapPanel、StackPanel(水平)和StackPanel(垂直)。例如:

<Style x:Key="listBoxStyle1" TargetType={x:Type ListBox}">
    <Setter Property="ItemsPanel">
        <Setter.Value>
            <ItemsPanelTemplate>
               <WrapPanel />
            </ItemsPanelTemplate>
        </Setter.Value>
    </Setter>
</Style>

这是一个品味问题,但我会触发淡出和淡入动画,时间可能为.15秒或.2秒,并在淡出时切换模板。这既可以隐藏滚动,也可以平滑布局中非常突然的切换。

您要查找的内容与我在前面的回答中所写的内容没有太大区别

两个区别是:

  • 您的目标似乎是阻止当前项目移动,而不是让它移动到中心。这实际上是可能的,并且和将其居中一样容易
  • 您的代码计时允许即时显示未滚动的版本,从而导致跳跃
  • 这两个问题可以一起解决,如下所示(有关代码详细信息,请参考我先前的回答):

  • 使用
    box.ItemContainerGenerator.ContainerFromItem(box.SelectedItem)
    获取项目容器
  • 调用
    container.TransformToAncestor(box).Transform(new Point())
    获取容器相对于列表框的左上角。(如果您希望保持项目中心静止,请使用
    新点(container.DesiredSize.Width/2,container.DesiredSize.Height/2)
    。)
  • 根据需要更改ItemTemplate或样式
  • 强制立即重新测量(简单的方法是调用UpdateLayout)
  • 再次使用
    box.ItemContainerGenerator.ContainerFromItem(box.SelectedItem)
    获取项目容器
  • 再次调用
    container.TransformToAncestor(box).Transform(new Point())
    以获取新容器相对于列表框的左上角
  • 使用我的另一个答案中的代码查找IScrollInfo并更新水平偏移量和垂直偏移量,以将新容器带到与旧容器相同的位置
  • 这将在没有闪烁的情况下工作的原因是这里的一切都是同步发生的,因此不会运行具有渲染优先级的调度程序操作。代价是UpdateLayout()相对昂贵

    还请注意,如果实现的任何单个项在初始测量/排列(例如在dispatcher回调中)后更改了其大小,则需要重新定位两次:一次在同步代码中,然后再次在dispatcher回调中。在这种情况下,我所知道的防止闪烁的唯一可靠的通用方法是在初始布局完成之前修复项目的实现,以获得正确的大小