[英]WPF dynamic datagrid binding methods
我沒有使用c#編程和使用WPF的豐富經驗,如果我的“詞匯”不夠技術或適當,我深表歉意。
我需要在應用程序中顯示一個表,其中行是類的實例,而列是定義我的對象的properties/attributes
。
public class myObject
{
//constructor
public myObject() { }
//properties
public string Topic { get; set}
public string Description { get; set; }
public bool Display { get; set; }
public List<myAttribute> AttributeList { get; set; }
//method
public string GetAttributeValueByName(string sAttributeName)
{
foreach (myAttribute A in this.AttributeList)
{
if (A.Name == sAttributeName) { return A.Value.ToString(); }
}
return string.Empty;
}
}
我有一個以datagrid.ItemSource
綁定的myObjects
列表,並且我已經能夠正確綁定定義的屬性(例如Topic / Description)並在列中顯示它們。 myObject.Display
是單向綁定的,可以讓我在數據網格中可視化myObject
或不可視化(作為一種來自其他地方的過濾器)。
現在,如您在上面的代碼中注意到的那樣,我有一個屬性,可以為我返回一個屬性列表。 這是因為myObject
具有用戶可以設置的未定義數量的可用屬性 。 我已經為這個正確的類屬性(與像一些簡單的特性.Name
, .Value
, .Color
, .Rank
)。 我有一些方法可以讓我檢索例如字符串形式的值。
我的主要問題是我無法在數據網格中正確可視化它們,因為通常情況下,綁定僅對屬性有效,而對方法無效。 我做了一些有關綁定方法的研究,並且嘗試了任何成功的結果。
簡述:
UI類:
namespace myApp.UserInterface
{
public partial class control : UserControl
{
control()
{
InitializeComponent();
InitializeData();
}
private InitializeData()
{
datagrid.ItemsSource = Core.myObjectPoolList;
}
}
}
UI XAML
<UserControl x:Class="myApp.UserInterface.control"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:myApp.UserInterface;assembly="
xmlns:core="clr-namespace:myObject.Core;assembly="
xmlns:system="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<ObjectDataProvider x:Key="basic_attribute_value"
ObjectType="{x:Type core:D2P_Issue}"
MethodName="GetAttributeValueByName"
IsAsynchronous="True">
<ObjectDataProvider.MethodParameters>
<system:String>status</system:String>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</UserControl.Resources>
<Grid>
<DataGrid Name="issuepool_datagrid" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Topic" Binding="{Binding Topic}" Width="150" TextBlock.TextAlignment="Center"/>
<DataGridTextColumn Header="Description" Binding="{Binding Description}" Width="150" TextBlock.TextAlignment="Center"/>
<DataGridTextColumn x:Name="status_column" Header="status" Binding="{Binding Source={StaticResource basic_attribute_value}, Mode=OneWay}" Width="150" TextBlock.TextAlignment="Center"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</UserControl>
在此示例中,我試圖留下動態生成的列,而僅對其進行硬編碼以查找“狀態”屬性名稱。
隨意詢問是否不清楚。
您可以在后面的代碼中動態創建列。 雖然很簡單。 如果要在同一項目中多次重用此代碼,則可以將其重寫為附加行為,並使用另一個附加屬性將動態列的集合存儲在網格本身上。
由您確定屬性集何時更改,並相應地更新列。 如果您偶然發現僅添加或刪除了一個屬性,則將動態列存儲在字典中以簡化智能更新它們的業務。
如果是的話,我也將myObject.AttributeList
替換為Dictionary<String, myAttribute>
。 綁定路徑必須稍作更改。
這使用戶可以編輯屬性值。 如果願意,可以在動態列上設置IsReadOnly = true
。
public partial class control : UserControl
{
control()
{
InitializeComponent();
InitializeData();
}
private InitializeData()
{
datagrid.ItemsSource = Core.myObjectPoolList;
var firstItem = Core.myObjectPoolList.First();
if (firstItem != null) {
UpdateDataGridColumns(dataGrid, firstItem.AttributeList, _dynamicColumns);
}
}
private Dictionary<string, DataGridColumn> _dynamicColumns = new Dictionary<string, DataGridColumn>();
protected void UpdateDataGridColumns(DataGrid dg, List<myAttribute> attributesSample, Dictionary<string, DataGridColumn> existingDynamicColumns)
{
foreach (var col in existingDynamicColumns.Values)
{
dg.Columns.Remove(col);
}
existingDynamicColumns.Clear();
int idx = 0;
foreach (var attr in attributesSample)
{
var column = new DataGridTextColumn() {
Header = attr.Name,
Binding = new Binding($"AttributeList[{idx}].Value")
};
dg.Columns.Add(column);
existingDynamicColumns.Add(attr.Name, column);
++idx;
}
}
}
替代方法:將所有屬性放在一欄中。 這不使用上面的代碼。 此格式是只讀的,但是可以修改為允許用戶編輯網格中的值。
將此屬性添加到myObject
:
public IEnumerable<String> AttributeNames
=> AttributeList.Select(a => a.Name);
這就是XAML中的DataGrid.Columns
:
<DataGridTemplateColumn
Width="*"
>
<DataGridTemplateColumn.HeaderStyle>
<Style>
<Setter Property="ContentControl.HorizontalContentAlignment" Value="Stretch" />
</Style>
</DataGridTemplateColumn.HeaderStyle>
<DataGridTemplateColumn.HeaderTemplate>
<DataTemplate>
<ItemsControl
ItemsSource="{Binding DataContext.Items[0].AttributeNames, RelativeSource={RelativeSource AncestorType=DataGrid}}"
>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Label
Content="{Binding}"
/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</DataGridTemplateColumn.HeaderTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ItemsControl
ItemsSource="{Binding AttributeList}"
>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Value}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
為什么不使用DataGridComboBoxColumn ?
像這樣:
<DataGridComboBoxColumnHeader="Attributes" Binding="{Binding AttributeList}" width="150" TextBlock.TextAlignment="Center"/>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.