手动创建未绑定的数据网格

时间:2009-02-20 17:48:32

标签: .net wpf windows

有人能告诉我是否可以创建数据并将数据添加到未绑定的WPF Toolkit数据网格。

如果事实上可以做,有人可以提供以下示例:

编程: 创建一个数据网格 创建datagridtextcolumn 将datagridtextcolumn添加到datagrid 创建一个datagridrow 将行的datagridtextcolumn的文本设置为“test” 将datagridrow添加到datagrid

我想创建一个未绑定的数据网格。我的理由是我想创建一个模板列,其中包含多个不同类型和数字的控件 - 2个复选框,4个单选按钮,5个复选框等 - 这些都是在运行时动态添加的,因为类型和编号未知也无法想到一种数据绑定方式。我很乐意无拘无束地工作。

提前谢谢!

[编辑:我还没有找到这个问题的合适答案并开始获得奖励]

3 个答案:

答案 0 :(得分:1)

我从来没有使用网格而没有绑定它。

但是 查看潜在原因,可以在使用数据绑定时解决。

例如: 如果您为绑定网格的对象使用ViewModel类,则可以将该类的一个方面设置为各种控件的可见性设置器。

在对象中,你有这个:

Public ReadOnly Property CheckboxAVisibility As Windows.Visibility
   Get
     ' Do Logic 
     Return Visiblity 
   End Get
End Property

在XAML中你会这样做:

<CheckBox IsChecked="{Binding IsBoxAChecked}" Visibility={Binding CheckboxAVisibility}" />

这也使事情变得更容易,因为您可以通过修改行中的其他控件来修改各种控件的可见性(例如:取消选中CheckboxA会导致RadioButtons B,C&amp; D出现)。

第二个选项是在网格中仅列出“标题”信息,当用户双击一行时,您将在辅助面板或窗口中显示带有可编辑方面的编辑器(类似于MVC编辑的工作方式) )。

因评论而修改

这是另一个建议,而不是数据网格,使用StackPanel。对于您需要的每一行,您可以添加一个网格面板或堆栈面板或类似的东西,根据您的规则在运行时创建。例如:

XAML:

<StackPanel Name="stkItems" Orientation="Vertical" />

代码:

Public Sub AddItems(dt as DataTable)
   For Each row As DataRow in dt.Rows
     Select Case row("Which")
          Case 1:
             Dim i As New Checkbox
             i.Content = "Foo"
             i.IsChecked = row("Content")
             stkItems.Children.Add(i)
          Case 2:
              Dim i as New TextBox
              i.Text = row("Content")
              stkItems.Children.Add(i)
     End Select
   Next
End Sub

这是高度简化的,你可以做一些事情,比如你可以使用预定义的用户控件,或者只是在程序定义的容器中构建一堆控件,然后将它添加到StackPanel

答案 1 :(得分:1)

您可以使用将创建所需控件的UserControl。

Window1.xaml(摘录)

<dg:DataGrid ItemsSource="{Binding}" CanUserAddRows="False" AutoGenerateColumns="False">
    <dg:DataGrid.Columns>

       <dg:DataGridTemplateColumn Header="Test" MinWidth="100">
            <dg:DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <my:ControlA Foo="{Binding}"></my:ControlA>
                </DataTemplate>
            </dg:DataGridTemplateColumn.CellTemplate>
        </dg:DataGridTemplateColumn>

    </dg:DataGrid.Columns>
</dg:DataGrid>

Window1.xaml.cs

public partial class Window1 : Window
{
    List<Foo> _items = new List<Foo>();

    public Window1()
    {
        InitializeComponent();

        _items.Add(new Foo { CheckBoxCount = 2, TextBoxCount = 1 });
        _items.Add(new Foo { CheckBoxCount = 3, TextBoxCount = 0 });

        DataContext = _items;
    }
}

ControlA.xaml

<UserControl x:Class="Demo.ControlA"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel x:Name="_placeHolder">
    </StackPanel>
</UserControl>

ControlA.xaml.cs

public partial class ControlA : UserControl
{
    public ControlA()
    {
        InitializeComponent();

        Loaded += new RoutedEventHandler(ControlA_Loaded);
    }

    void ControlA_Loaded(object sender, RoutedEventArgs e)
    {
        if (Foo != null)
        {
            for (int it = 0; it < Foo.CheckBoxCount; it++)
                _placeHolder.Children.Add(new CheckBox());

            for (int it = 0; it < Foo.TextBoxCount; it++)
                _placeHolder.Children.Add(new TextBox());
        }
    }

    public static readonly DependencyProperty FooProperty =
        DependencyProperty.Register("Foo", typeof(Foo), typeof(ControlA));

    public Foo Foo
    {
        get { return (Foo)GetValue(FooProperty); }
        set { SetValue(FooProperty, value); }
    }
}

Foo.cs

public class Foo
{
    public int TextBoxCount { get; set; }
    public int CheckBoxCount { get; set; }
}

希望这有帮助。

P.S。应该可以将refactor DataGridTemplateColumn分成单独的UserControl。

答案 2 :(得分:0)

我创建了一个简单的DataGridUnboundedColumn类,它派生自DataGridBoundColumn,可用于为单元格提供FrameworkElement的自定义文本。

您只需订阅CellFormating事件,并将EventArgs中的CellElement设置为将要显示的自定义元素。也可以在EventArgs中设置CellText - 在这种情况下,带有CellText的TextBlock将显示在Grid中。

以下示例显示了如何使用它:

XAML:

<dg:DataGrid Name="DataGrid1" AutoGenerateColumns="False">
    <dg:DataGrid.Columns>
        <dg:DataGridTextColumn Header="Name" Binding="{Binding Path=Name}"/>
        <myColumn:DataGridUnboundedColumn x:Name="AddressColumn" Header="Address" />
    </dg:DataGrid.Columns>
</dg:DataGrid>

CODE:

   public MyPage()
    {
        InitializeComponent();

        AddressColumn.CellFormating += new UnboundedColumnEventHandler(AddressColumn_CellFormating);
    }

    void AddressColumn_CellFormating(object sender, UnboundedColumnEventArgs e)
    {
        IPerson person;

        person= e.DataItem as IPerson;

        if (person!= null)
            e.CellText = string.Format("{0}, {1} {2}", person.Address, person.PostalCode, person.City);
    }

DataGridUnboundedColumn实现在这里:

class DataGridUnboundedColumn : DataGridBoundColumn
{
    public event UnboundedColumnEventHandler CellFormating;

    public DataGridUnboundedColumn()
    {
        this.IsReadOnly = true;
    }

    protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
    {
        return null;
    }

    protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
    {
        FrameworkElement shownElement;
        UnboundedColumnEventArgs eventArgs;

        if (CellFormating == null)
            return null;


        eventArgs = new UnboundedColumnEventArgs(cell, dataItem);

        // call the event
        CellFormating(this, eventArgs);

        shownElement = null;

        // check the data set in the eventArgs
        if (eventArgs.CellElement != null)
        {
            // show the set eventArgs.CellElement
            shownElement = eventArgs.CellElement;
        }
        else if (eventArgs.CellText != null)
        {
            // show the CellText in TextBlock
            TextBlock textBlock = new TextBlock();
            textBlock.Text = eventArgs.CellText;

            shownElement = textBlock;
        }
        else
        {
            // nothing set
        }

        return shownElement;
    }
}

public delegate void UnboundedColumnEventHandler(object sender, UnboundedColumnEventArgs e);

public class UnboundedColumnEventArgs : EventArgs
{
    public DataGridCell Cell { get; set; }
    public object DataItem { get; set; }

    /// <summary>
    /// The subscriber of the event can set the CellText.
    /// In this case the TextBlock is used to display the text.
    /// NOTE that if CellElement is not null, the CellText will not be used but insted a CellElement will be shown
    /// </summary>
    public string CellText { get; set; }

    /// <summary>
    /// The subscribed can set the FrameworkElement that will be shown for this cell.
    /// If the CellElement is null, the CellText will be used to show the TextBlock
    /// </summary>
    public FrameworkElement CellElement { get; set; }

    public UnboundedColumnEventArgs()
        : base()
    { }

    public UnboundedColumnEventArgs(DataGridCell cell, object dataItem)
        : base()
    {
        Cell = cell;
        DataItem = dataItem;
    }
}
相关问题