Создать несвязанную сетку данных вручную - PullRequest
2 голосов
/ 20 февраля 2009

Может кто-нибудь сказать мне, возможно ли создавать и добавлять данные в несвязанную сетку данных WPF Toolkit.

Если это действительно возможно, может кто-нибудь привести пример следующего:

Программное: создать сетку данных создать столбец данных добавить столбец данных в столбец данных создать сетку данных установить текст столбца данных для строки «test» добавить сетку данных в сетку данных

Я хотел бы создать несвязанную сетку данных. Моя причина в том, что я хотел бы создать столбец шаблона с несколькими элементами управления разных типов и чисел - 2 флажка, 4 радиокнопки, 5 флажков и т. Д. - которые динамически добавляются во время выполнения, и так как тип и номер неизвестны, не могу придумать способ привязать их к данным. Я счастлив работать без ограничений.

Заранее спасибо!

[Редактировать: я еще не нашел подходящего ответа на этот вопрос и начал вознаграждение]

Ответы [ 3 ]

1 голос
/ 09 апреля 2009

Вы можете использовать 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. Должна быть возможность рефакторинг DataGridTemplateColumn в отдельный UserControl.

1 голос
/ 20 февраля 2009

Я никогда не использовал сетку, не привязывая ее к чему-либо.

НО с учетом основной причины, которая может быть решена при использовании привязки данных.

Например: Если вы используете класс 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}" />

Это также облегчает задачу, так как вы сможете изменять видимость различных элементов управления путем изменения других элементов управления в строке (например, снятие флажка с флажка A приводит к появлению кнопок RadioButton B, C & 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

0 голосов
/ 13 августа 2009

Я создал простой класс DataGridUnboundedColumn, который является производным от DataGridBoundColumn и может использоваться для предоставления пользовательского текста FrameworkElement для ячейки.

Вы просто подписываетесь на событие CellFormating и устанавливаете CellElement в EventArgs для настраиваемого элемента, который будет отображаться. Также возможно установить только CellText в EventArgs - в этом случае TextBlock с CellText будет показан в 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>

КОД:

   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;
    }
}
...