如何在 WPF ListView 列按比例调整大小时避免水平滚动条
How To Avoid Horizontal Scrollbar During Proportional Resize of WPF ListView Columns
目标:在 WPF 网格中,当 window 大小更改时,以编程方式调整子 ListView 中列的大小,保持相对列大小,而不会显示水平滚动条。
目前,按比例调整大小效果很好,只是当我减小 window 的宽度时,我会得到一个水平滚动条,它只滚动了很少量的 space。我想知道这是否是由于宽度 属性 没有考虑列之间的图形分隔符?.. 或..?
导致问题的部分是最后一节,我扩展了最后一列的宽度以填充 space 的其余部分。我不想减去我从试验和错误中产生的一些神奇数字(这可能在一定程度上起作用)。
..是的,最终我会解释垂直滚动条的存在(或不存在),但现在我只想避免看到水平滚动条。
这是调整 ListView 列大小的代码:
LV_FileList.SizeChanged += this.onLV_FileList_SizeChanged;
...
/// <summary>
/// Proportionally resize listview columns when listview size changes
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void onLV_FileList_SizeChanged(object sender, SizeChangedEventArgs e)
{
if ((sender is ListView) &&
(e.PreviousSize.Width > 0))
{
double total_width = 0;
GridViewColumnCollection gvcc = ((GridView)(sender as ListView).View).Columns;
foreach (GridViewColumn gvc in gvcc)
{
gvc.Width = (gvc.Width / e.PreviousSize.Width) * e.NewSize.Width;
total_width += gvc.Width;
}
//Increase width of last column to fit width of listview if integer division made the total width to small
if (total_width < e.NewSize.Width)
{
gvcc[gvcc.Count - 1].Width += (e.NewSize.Width - total_width);
}
}
}
我在有问题的部分添加了一个 While 循环,但不幸的是它无法正常工作。 ComputedHorizontalScrollBarVisibilityProperty 值永远不会随着最后一列的宽度减小而改变,因此它只是变为 0 并针对列的宽度抛出无效值异常。我什至尝试在循环中调用 LV_FileList.UpdateLayout() ,认为在水平滚动条消失之前可能需要刷新列表视图控件的显示或其他内容。没有骰子。
//Increase width of last column to fit width of listview if integer division made the total width to small
if (total_width < e.NewSize.Width)
{
gvcc[gvcc.Count - 1].Width += (e.NewSize.Width - total_width);
while ((Visibility)LV_FileList.GetValue(ScrollViewer.ComputedHorizontalScrollBarVisibilityProperty) == Visibility.Visible)
{
gvcc[gvcc.Count - 1].Width--;
//LV_FileList.UpdateLayout(); <-- doesn't help
}
}
将 HorizontalScrollBarVisibility
属性 设置为禁用即可。
myListView.SetValue(ScrollViewer.HorizontalScrollBarVisibilityProperty,
ScrollBarVisibility.Disabled);
或在XAML...
<ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled">
这是我最终得到的结果。它也处理垂直滚动条。到目前为止我发现的一个缺点是水平滚动条有时会在用户调整 window 大小时短暂闪烁。如果有人知道更好的方法,请post!谢谢!
/// <summary>
/// Proportionally resize listview columns when listview size changes
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void onLV_FileList_SizeChanged(object sender, SizeChangedEventArgs e)
{
if ((sender is ListView) &&
(e.PreviousSize.Width > 0))
{
double total_width = 0;
GridViewColumnCollection gvcc = ((GridView)(sender as ListView).View).Columns;
foreach (GridViewColumn gvc in gvcc)
{
gvc.Width = (gvc.Width / e.PreviousSize.Width) * e.NewSize.Width;
total_width += gvc.Width;
}
//Increase width of last column to fit width of listview if integer division made the total width to small
if (total_width < e.NewSize.Width)
{
gvcc[gvcc.Count - 1].Width += (e.NewSize.Width - total_width);
}
//Render changes to ListView before checking for horizontal scrollbar
this.AllowUIToUpdate();
//Decrease width of last column to eliminate scrollbar if it is displayed now
ScrollViewer svFileList = this.FindVisualChild<ScrollViewer>(LV_FileList);
while ((svFileList.ComputedHorizontalScrollBarVisibility != Visibility.Collapsed) && (gvcc[gvcc.Count - 1].Width > 1))
{
gvcc[gvcc.Count - 1].Width--;
this.AllowUIToUpdate();
}
}
}
/// <summary>
/// Threaded invocation to handle updating UI in resize loop
/// </summary>
private void AllowUIToUpdate()
{
DispatcherFrame dFrame = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Render, new DispatcherOperationCallback(delegate(object parameter)
{
dFrame.Continue = false;
return null;
}), null);
Dispatcher.PushFrame(dFrame);
}
目标:在 WPF 网格中,当 window 大小更改时,以编程方式调整子 ListView 中列的大小,保持相对列大小,而不会显示水平滚动条。
目前,按比例调整大小效果很好,只是当我减小 window 的宽度时,我会得到一个水平滚动条,它只滚动了很少量的 space。我想知道这是否是由于宽度 属性 没有考虑列之间的图形分隔符?.. 或..?
导致问题的部分是最后一节,我扩展了最后一列的宽度以填充 space 的其余部分。我不想减去我从试验和错误中产生的一些神奇数字(这可能在一定程度上起作用)。
..是的,最终我会解释垂直滚动条的存在(或不存在),但现在我只想避免看到水平滚动条。
这是调整 ListView 列大小的代码:
LV_FileList.SizeChanged += this.onLV_FileList_SizeChanged;
...
/// <summary>
/// Proportionally resize listview columns when listview size changes
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void onLV_FileList_SizeChanged(object sender, SizeChangedEventArgs e)
{
if ((sender is ListView) &&
(e.PreviousSize.Width > 0))
{
double total_width = 0;
GridViewColumnCollection gvcc = ((GridView)(sender as ListView).View).Columns;
foreach (GridViewColumn gvc in gvcc)
{
gvc.Width = (gvc.Width / e.PreviousSize.Width) * e.NewSize.Width;
total_width += gvc.Width;
}
//Increase width of last column to fit width of listview if integer division made the total width to small
if (total_width < e.NewSize.Width)
{
gvcc[gvcc.Count - 1].Width += (e.NewSize.Width - total_width);
}
}
}
我在有问题的部分添加了一个 While 循环,但不幸的是它无法正常工作。 ComputedHorizontalScrollBarVisibilityProperty 值永远不会随着最后一列的宽度减小而改变,因此它只是变为 0 并针对列的宽度抛出无效值异常。我什至尝试在循环中调用 LV_FileList.UpdateLayout() ,认为在水平滚动条消失之前可能需要刷新列表视图控件的显示或其他内容。没有骰子。
//Increase width of last column to fit width of listview if integer division made the total width to small
if (total_width < e.NewSize.Width)
{
gvcc[gvcc.Count - 1].Width += (e.NewSize.Width - total_width);
while ((Visibility)LV_FileList.GetValue(ScrollViewer.ComputedHorizontalScrollBarVisibilityProperty) == Visibility.Visible)
{
gvcc[gvcc.Count - 1].Width--;
//LV_FileList.UpdateLayout(); <-- doesn't help
}
}
将 HorizontalScrollBarVisibility
属性 设置为禁用即可。
myListView.SetValue(ScrollViewer.HorizontalScrollBarVisibilityProperty,
ScrollBarVisibility.Disabled);
或在XAML...
<ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled">
这是我最终得到的结果。它也处理垂直滚动条。到目前为止我发现的一个缺点是水平滚动条有时会在用户调整 window 大小时短暂闪烁。如果有人知道更好的方法,请post!谢谢!
/// <summary>
/// Proportionally resize listview columns when listview size changes
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void onLV_FileList_SizeChanged(object sender, SizeChangedEventArgs e)
{
if ((sender is ListView) &&
(e.PreviousSize.Width > 0))
{
double total_width = 0;
GridViewColumnCollection gvcc = ((GridView)(sender as ListView).View).Columns;
foreach (GridViewColumn gvc in gvcc)
{
gvc.Width = (gvc.Width / e.PreviousSize.Width) * e.NewSize.Width;
total_width += gvc.Width;
}
//Increase width of last column to fit width of listview if integer division made the total width to small
if (total_width < e.NewSize.Width)
{
gvcc[gvcc.Count - 1].Width += (e.NewSize.Width - total_width);
}
//Render changes to ListView before checking for horizontal scrollbar
this.AllowUIToUpdate();
//Decrease width of last column to eliminate scrollbar if it is displayed now
ScrollViewer svFileList = this.FindVisualChild<ScrollViewer>(LV_FileList);
while ((svFileList.ComputedHorizontalScrollBarVisibility != Visibility.Collapsed) && (gvcc[gvcc.Count - 1].Width > 1))
{
gvcc[gvcc.Count - 1].Width--;
this.AllowUIToUpdate();
}
}
}
/// <summary>
/// Threaded invocation to handle updating UI in resize loop
/// </summary>
private void AllowUIToUpdate()
{
DispatcherFrame dFrame = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Render, new DispatcherOperationCallback(delegate(object parameter)
{
dFrame.Continue = false;
return null;
}), null);
Dispatcher.PushFrame(dFrame);
}