該
更新:
我要求描述行為的原因是在滑鼠單擊行的任何位置時選擇行。當我單擊該行的右側時,該行沒有選擇 - 沒有單元格。我通過添加這里MouseLeftButtonDown描述的事件處理程式來實作這一點。
uj5u.com熱心網友回復:
的UpdateLayout通話是完全多余的。修改Width將自動觸發布局傳遞。此外,應該將兩個迭代合并為一個迭代以提高性能。
完整的實作在用戶體驗方面非常值得懷疑:如果用戶調整列的寬度,您將覆寫并重置他的自定義,這會提供很差的體驗。此外,網格可能會不斷調整自身大小,這看起來和感覺也很奇怪。您至少應該設定DataGrid.CanUserResizeColumns為false.
我相信添加一個列過濾器,允許用戶隱藏特定列以壓縮視圖,具有更高的價值。
從您發布的代碼中,無法確切說明發生了什么或可能導致問題的原因。您的DataGrid控制元件及其背景關系的實際布局配置顯然未公開。
但是,問題可能與如何DataGrid計算每列的寬度有關,以防萬一您給出DataGrid固定Width值,并且此值會導致內容超出可用視口寬度(ScrollViewer在這種情況下會出現):
a) 在每列寬度設定為 的情況下Auto,DataGrid將簡單地為每列提供所需的最小寬度。
b) 如果列的寬度設定為星號*,則分配的寬度是相對于可用剩余空間計算的。
為了計算出一個合理的值,演算法將使用 的有效大小DataGrid。
關鍵是,當使用 a 時ScrollViewer,虛擬寬度將是無限的。現在,如果演算法將最后一列的寬度設定為無限大,您將得到一個非常小的滾動條。因此,無窮大不是一個合理的值。實際上,無法計算最終寬度。這就是為什么演算法回退到使用 的有效寬度DataGrid,也就是ScrollViewer.ViewportWidth。結果是所有列都必須被擠壓到可用的視口空間中,從而導致列剪裁其標題和單元格內容。
我可以提供兩種解決方案。
第一種解決方案是對Width最后一列使用固定值,如1000DIP。
這個解決方案的規模非常糟糕。最后一列的寬度要么太小,要么太寬,沒有多大意義(這就是為什么無法計算最后一列的合理寬度 - 在這種情況下什么是合理的?)。
第二個更好的解決方案將嘗試檢測是否ScrollViewer可以滾動:在這種情況下,最后一列至少部分在視野之外。這導致Width最后一列的合理Auto:所需的最小空間。
另一種情況是ScrollViewer無法滾動時,所有列都在視口中可見。這導致合理Width的*為了讓最后一列填充剩余空間:
private void OnLoadingRow(object sender, DataGridRowEventArgs e)
{
var dataGrid = sender as DataGrid;
foreach (var dataGridColumn in dataGrid.Columns)
{
dataGridColumn.Width = 0;
dataGridColumn.Width = DataGridLength.Auto;
}
if (TryFindVisualChildElementByName(dataGrid, string.Empty, out ScrollViewer scrollViewer)
&& scrollViewer.ScrollableWidth == 0)
{
dataGrid.Columns.Last().Width = new DataGridLength(1, DataGridLengthUnitType.Star);
}
}
public static bool TryFindVisualChildElementByName<TChild>(
DependencyObject parent,
string childElementName,
out TChild resultElement) where TChild : FrameworkElement
{
resultElement = null;
if (parent is Popup popup)
{
parent = popup.Child;
if (parent == null)
{
return false;
}
}
for (var childIndex = 0; childIndex < VisualTreeHelper.GetChildrenCount(parent); childIndex )
{
DependencyObject childElement = VisualTreeHelper.GetChild(parent, childIndex);
if (childElement is TChild frameworkElement)
{
if (string.IsNullOrWhiteSpace(childElementName)
|| frameworkElement.Name.Equals(childElementName, StringComparison.OrdinalIgnoreCase))
{
resultElement = frameworkElement;
return true;
}
}
if (TryFindVisualChildElementByName(childElement, childElementName, out resultElement))
{
return true;
}
}
return false;
}
uj5u.com熱心網友回復:
似乎DataGrid無法一次性處理所有更改,但是您可以“錯開”更新并通過將最后一部分放在事件回圈中來執行“中間”布局,例如,如下所示:
private void OnLoadingRow(object sender, DataGridRowEventArgs e)
{
if (sender is not DataGrid dg) return;
foreach (var c in dg.Columns) c.Width = 0;
foreach (var c in dg.Columns.SkipLast(1)) c.Width = DataGridLength.Auto;
Dispatcher.BeginInvoke((DataGridColumn lc) => lc.Width = new DataGridLength(1, DataGridLengthUnitType.Star), dg.Columns.Last());
}
這不是一個很好的解決方案,并且由于列寬的可見變化,網格會有點閃爍。也許可以改進,例如,通過檢測何時真正需要“重置”寬度。你決定它是否足夠好。
編輯 - 通過在中間布局期間將最后一列設定為相同的寬度,這是一個稍微不那么閃爍的版本:
private void OnLoadingRow(object sender, DataGridRowEventArgs e)
{
if (sender is not DataGrid dg) return;
foreach (var c in dg.Columns.SkipLast(1)) c.Width = 0;
var lastColumn = dg.Columns.Last();
lastColumn.Width = lastColumn.ActualWidth;
foreach (var c in dg.Columns.SkipLast(1)) c.Width = DataGridLength.Auto;
Dispatcher.BeginInvoke((DataGridColumn lc) =>
lc.Width = new DataGridLength(1, DataGridLengthUnitType.Star), lastColumn);
}
編輯 2 - 重構以使其更清晰:
private void OnLoadingRow(object sender, DataGridRowEventArgs e)
{
if (sender is not DataGrid dg) return;
foreach (var c in dg.Columns.SkipLast(1))
{
c.Width = 0;
c.Width = DataGridLength.Auto;
}
var lastColumn = dg.Columns.Last();
lastColumn.Width = lastColumn.ActualWidth;
Dispatcher.BeginInvoke(static (DataGridColumn lc) =>
lc.Width = new DataGridLength(1, DataGridLengthUnitType.Star), lastColumn);
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/371410.html
上一篇:根據選項卡的數量自動調整選項卡標題的大小(AvaloniaUI)
下一篇:列印流程檔案為表格添加邊框
