簡體   English   中英

WPF動態數據網格綁定方法

[英]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 )。 我有一些方法可以讓我檢索例如字符串形式的值。

我的主要問題是我無法在數據網格中正確可視化它們,因為通常情況下,綁定僅對屬性有效,而對方法無效。 我做了一些有關綁定方法的研究,並且嘗試了任何成功的結果。

簡述:

  • 我需要動態列(一些固定的主題,例如主題+每個屬性一個)
  • 所有myObject在AttributeList中具有相同數量的元素
  • 我需要將屬性值綁定(至少是一種方式)在datagrid的適當單元格中。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM