как автоматически изменять размер и выравнивать данные gridviewcolumn в wpf?

<p>как я могу:</p><ul> <li>выровнять текст в столбце идентификатора вправо</li> <li>сделать каждый из столбцов автоматическим размером в соответствии с длиной текста ячейки с самыми длинными видимыми данными?</li> </ul><p>вот код:</p><pre><code><listview name="lstcustomers" itemssource="{binding path=collection}"> <listview.view> <gridview> <gridviewcolumn header="id" displaymemberbinding="{binding id}" width="40"/> <gridviewcolumn header="first name" displaymemberbinding="{binding firstname}" width="100" /> <gridviewcolumn header="last name" displaymemberbinding="{binding lastname}"/> </gridview> </listview.view> </listview> </code></pre><h2>частичный ответ:</h2><p>благодаря kjetil, gridviewcolumn.celltemplate работает хорошо, и auto width работает, конечно, но когда "коллекция" observativecollection обновляется данными, длина которых превышает ширину столбца, размеры столбцов не обновляются, так что это только решение для первоначальное отображение данных:</p><pre><code><listview name="lstcustomers" itemssource="{binding path=collection}"> <listview.view> <gridview> <gridviewcolumn header="id" width="auto"> <gridviewcolumn.celltemplate> <datatemplate> <textblock text="{binding id}" textalignment="right" width="40"/> </datatemplate> </gridviewcolumn.celltemplate> </gridviewcolumn> <gridviewcolumn header="first name" displaymemberbinding="{binding firstname}" width="auto" /> <gridviewcolumn header="last name" displaymemberbinding="{binding lastname}" width="auto"/> </gridview> </listview.view> </listview> </code></pre>

<p>чтобы сделать каждый столбец автоматически изменяемым, вы можете установить width = "auto" в gridviewcolumn.</p><p>чтобы выровнять текст в столбце id по правому краю, вы можете создать шаблон ячейки с помощью textblock и установить textalignment. затем установите listviewitem.hor horizontalcontentalignment (используя стиль с установщиком в listviewitem), чтобы шаблон ячейки заполнил весь gridviewcell.</p><p>может быть, есть более простое решение, но это должно работать.</p><p><strong>примечание:</strong> для решения требуется оба параметра <strong>horizontalcontentalignment = stretch</strong> в window.resources и <strong>textalignment = right</strong> в шаблоне celltemplate.</p><pre><code><window x:class="wpfapplication6.window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" title="window1" height="300" width="300"> <window.resources> <style targettype="listviewitem"> <setter property="horizontalcontentalignment" value="stretch" /> </style> </window.resources> <grid> <listview name="lstcustomers" itemssource="{binding path=collection}"> <listview.view> <gridview> <gridviewcolumn header="id" width="40"> <gridviewcolumn.celltemplate> <datatemplate> <textblock text="{binding id}" textalignment="right" /> </datatemplate> </gridviewcolumn.celltemplate> </gridviewcolumn> <gridviewcolumn header="first name" displaymemberbinding="{binding firstname}" width="auto" /> <gridviewcolumn header="last name" displaymemberbinding="{binding lastname}" width="auto"/> </gridview> </listview.view> </listview> </grid> </window> </code></pre>

<p>если ширина содержимого изменяется, вам придется использовать этот бит кода для обновления каждого столбца:</p><pre><code>private void resizegridviewcolumn(gridviewcolumn column) { if (double.isnan(column.width)) { column.width = column.actualwidth; } column.width = double.nan; } </code></pre><p>вам придется запускать его каждый раз, когда обновляются данные для этого столбца.</p>

<p>если ваш просмотр списка также изменяет размеры, вы можете использовать шаблон поведения, чтобы изменить размер столбцов, чтобы он соответствовал полной ширине listview. почти так же, как вы используете определения grid.column</p><pre><code><listview horizontalalignment="stretch" behaviours:gridviewcolumnresize.enabled="true"> <listviewitem></listviewitem> <listview.view> <gridview> <gridviewcolumn header="column *" behaviours:gridviewcolumnresize.width="*" > <gridviewcolumn.celltemplate> <datatemplate> <textbox horizontalalignment="stretch" text="example1" /> </datatemplate> </gridviewcolumn.celltemplate> </code></pre><p>см. следующую ссылку для некоторых примеров и ссылки на исходный код <a href="http://lazycowprojects.tumblr.com/post/7063214400/wpf-c-listview-column-width-auto">http://lazycowprojects.tumblr.com/post/7063214400/wpf-c-listview-column-width-auto</a> </p>

<p>я создал следующий класс и использовал его во всем приложении вместо <code>gridview</code>:</p><pre class="lang-cs prettyprint-override"><code>/// <summary> /// represents a view mode that displays data items in columns for a system.windows.controls.listview control with auto sized columns based on the column content /// </summary> public class autosizedgridview : gridview { protected override void prepareitem(listviewitem item) { foreach (gridviewcolumn column in columns) { // setting nan for the column width automatically determines the required // width enough to hold the content completely. // if the width is nan, first set it to actualwidth temporarily. if (double.isnan(column.width)) column.width = column.actualwidth; // finally, set the column with to nan. this raises the property change // event and re computes the width. column.width = double.nan; } base.prepareitem(item); } } </code></pre>

<p>так как у меня был itemcontainerstyle, я должен был поместить horizontalcontentalignment в itemcontainerstyle</p><pre><code> <listview.itemcontainerstyle> <style targettype="listviewitem"> <style.triggers> <datatrigger binding="{binding path=fielddef.dispdetail, mode=oneway}" value="false"> <setter property="visibility" value="collapsed"/> </datatrigger> </style.triggers> <setter property="horizontalcontentalignment" value="stretch" /> .... </code></pre>

<p>мне понравилось решение user1333423 за исключением того, что оно всегда изменяло размер каждого столбца; мне нужно, чтобы некоторые столбцы были фиксированной ширины. таким образом, в этой версии столбцы с шириной, установленной в "авто", будут иметь автоматический размер, а столбцы с фиксированной суммой не будут иметь автоматический размер.</p><pre><code>public class autosizedgridview : gridview { hashset<int> \_autowidthcolumns; protected override void prepareitem(listviewitem item) { if (\_autowidthcolumns == null) { \_autowidthcolumns = new hashset<int>(); foreach (var column in columns) { if(double.isnan(column.width)) \_autowidthcolumns.add(column.gethashcode()); } } foreach (gridviewcolumn column in columns) { if (\_autowidthcolumns.contains(column.gethashcode())) { if (double.isnan(column.width)) column.width = column.actualwidth; column.width = double.nan; } } base.prepareitem(item); } } </code></pre>

<p>я знаю, что это слишком поздно, но вот мой подход:</p><pre><code><gridviewcolumn x:name="gridheaderlocalsize" width="100"> <gridviewcolumn.header> <gridviewcolumnheader horizontalcontentalignment="right"> <grid width="auto" horizontalalignment="right"> <grid.columndefinitions> <columndefinition width="100"/> </grid.columndefinitions> <textblock grid.column="0" text="local size" textalignment="right" padding="0,0,5,0"/> </grid> </gridviewcolumnheader> </gridviewcolumn.header> <gridviewcolumn.celltemplate> <datatemplate> <textblock width="{binding elementname=gridheaderlocalsize, path=width, fallbackvalue=100}" horizontalalignment="right" textalignment="right" padding="0,0,5,0" text="text" > </textblock> </datatemplate> </gridviewcolumn.celltemplate> </code></pre><p>основная идея состоит в том, чтобы привязать ширину элемента celltemplete к ширине viewgridcolumn. ширина = 100 - это ширина по умолчанию, используемая до первого изменения размера. там нет никакого кода позади. все в xaml.</p>

<p>у меня были проблемы с принятым ответом (потому что я пропустил часть horizontalalignment = stretch и скорректировал исходный ответ).</p><p>это еще одна техника. он использует grid с sharedsizegroup.</p><p><strong>примечание:</strong> the <strong>grid.issharedscope = true</strong> в listview.</p><pre><code><window x:class="wpfapplication6.window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" title="window1" height="300" width="300"> <grid> <listview name="lstcustomers" itemssource="{binding path=collection}" grid.issharedsizescope="true"> <listview.view> <gridview> <gridviewcolumn header="id" width="40"> <gridviewcolumn.celltemplate> <datatemplate> <grid> <grid.columndefinitions> <columndefinition width="auto" sharedsizegroup="idcolumn"/> </grid.columndefinitions> <textblock horizontalalignment="right" text={binding path=id}"/> </grid> </datatemplate> </gridviewcolumn.celltemplate> </gridviewcolumn> <gridviewcolumn header="first name" displaymemberbinding="{binding firstname}" width="auto" /> <gridviewcolumn header="last name" displaymemberbinding="{binding lastname}" width="auto"/> </gridview> </listview.view> </listview> </grid> </window> </code></pre>

<p>я создал функцию для обновления заголовков столбцов gridview для списка и вызываю ее всякий раз, когда окно изменяет размеры или когда список обновляет свой макет.</p><pre><code>public void correctcolumnwidths() { double remainingspace = mylist.actualwidth; if (remainingspace > 0) { for (int i = 0; i < (mylist.view as gridview).columns.count; i++) if (i != 2) remainingspace -= (mylist.view as gridview).columns[i].actualwidth; //leave 15 px free for scrollbar remainingspace -= 15; (mylist.view as gridview).columns[2].width = remainingspace; } } </code></pre>

<p>это твой код</p><pre><code><listview name="lstcustomers" itemssource="{binding path=collection}"> <listview.view> <gridview> <gridviewcolumn header="id" displaymemberbinding="{binding id}" width="40"/> <gridviewcolumn header="first name" displaymemberbinding="{binding firstname}" width="100" /> <gridviewcolumn header="last name" displaymemberbinding="{binding lastname}"/> </gridview> </listview.view> </listview> </code></pre><p>попробуй это</p><pre><code><listview name="lstcustomers" itemssource="{binding path=collection}"> <listview.view> <gridview> <gridviewcolumn displaymemberbinding="{binding id}" width="auto"> <gridviewcolumnheader content="id" width="auto" /> </gridviewcolumn> <gridviewcolumn displaymemberbinding="{binding firstname}" width="auto"> <gridviewcolumnheader content="first name" width="auto" /> </gridviewcolumn> <gridviewcolumn displaymemberbinding="{binding lastname}" width="auto"> <gridviewcolumnheader content="last name" width="auto" /> </gridviewcolumn </gridview> </listview.view> </listview> </code></pre>