Как установить ItemsPanelTemplate для динамически создаваемой сетки в коде позади - PullRequest
6 голосов
/ 06 декабря 2011

Я определил это UserControl в XAML и хотел бы динамически установить ItemsPanelTemplate в моем коде позади класса (а не в XAML, как в примере):

<UserControl>
    <ItemsControl x:Name="Items">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Grid> <!-- I want to add this Grid definition in code behind -->
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition />
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition />
                    </Grid.RowDefinitions>
                </Grid>
            </ItemsPanelTemplate>
       </ItemsControl.ItemsPanel>
    </ItemsControl>
</UserControl>

Я пробовал что-то вроде

this.Items.ItemsPanel.Template = new Grid();

, но с треском провалился.Любая помощь?

Справочная информация: Я знаю только количество столбцов сетки и строк во время выполнения.

Ответы [ 4 ]

4 голосов
/ 06 декабря 2011

Вам необходимо создать ItemsPanelTemplate и установить для VisualTree значение FrameworkElementFactory (устарело), ​​которое создает Grid, или использовать XamlReader parse XAML-строка, которая задает шаблон.

Этот вопрос содержит примеры использования обоих методов (хотя и для другого свойства шаблона).

Более простой способ управления панелью во время выполнения изложен в этом вопросе .

3 голосов
/ 15 марта 2013

Вы можете делать как хотите, создавая MannualCode в коде следующим образом: 1. Создайте метод следующим образом, который будет возвращать ItemsPanelTemplate

     private ItemsPanelTemplate GetItemsPanelTemplate()
    {
        string xaml = @"<ItemsPanelTemplate   xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition />
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition />
                                </Grid.RowDefinitions>
                            </Grid>
                    </ItemsPanelTemplate>";
        return XamlReader.Parse(xaml) as ItemsPanelTemplate;
    }
  1. Теперь добавьте этот шаблон в свойListbox ItemsPanel as:

       MyListBox.ItemsPanel = GetItemsPanelTemplate();
    

Это нормально работает для меня.Надеюсь, это поможет.

Продолжайте кодировать ....:)

0 голосов
/ 04 апреля 2019

Вот программа на XAML, которая использует ItemsPanelTemplate с Grid:

MainWindow.xaml:

<Window x:Class="WpfTutorialStatusBarGrid.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfTutorialStatusBarGrid"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <DockPanel>

        <StatusBar DockPanel.Dock="Bottom">

            <StatusBar.ItemsPanel>

                <ItemsPanelTemplate>

                    <Grid>

                        <Grid.ColumnDefinitions>

                            <ColumnDefinition Width="100" />
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="100" />

                        </Grid.ColumnDefinitions>

                    </Grid>

                </ItemsPanelTemplate>

            </StatusBar.ItemsPanel>

            <StatusBarItem Grid.Column="0">
                <TextBlock Name="lblCursorPosition" />
            </StatusBarItem>

            <Separator Grid.Column="1"/>

            <StatusBarItem Grid.Column="2">
                <TextBlock Text="c:\temp\abc.txt"/>
            </StatusBarItem>

            <Separator Grid.Column="3"/>

            <StatusBarItem Grid.Column="4">
                <ProgressBar Value="50" Width="90" Height="16"/>
            </StatusBarItem>

        </StatusBar>

        <TextBox AcceptsReturn="True" Name="txtEditor" SelectionChanged="TxtEditor_SelectionChanged"/>

    </DockPanel>

</Window>

MainWindow.xaml.cs:

using System.Windows;

namespace WpfTutorialStatusBarGrid
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void TxtEditor_SelectionChanged(object sender, RoutedEventArgs e)
        {
            var row = txtEditor.GetLineIndexFromCharacterIndex(txtEditor.CaretIndex);
            var col = txtEditor.CaretIndex - txtEditor.GetCharacterIndexFromLineIndex(row);

            lblCursorPosition.Text = $"Line {row + 1}, Char {col + 1}";
        }
    }
}

Это простой текстовый редактор со строкой состояния:

enter image description here

Вот эквивалентная программа с кодом на C # вместо XAML:

MainWindow.xaml:

<Window x:Class="WpfTutorialStatusBarGridCs.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfTutorialStatusBarGridCs"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>

    </Grid>
</Window>

MainWindow.xaml.cs:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;

namespace WpfTutorialStatusBarGridCs
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            var dock_panel = new DockPanel();

            Content = dock_panel;


            var status_bar = new StatusBar();

            dock_panel.Children.Add(status_bar);

            DockPanel.SetDock(status_bar, Dock.Bottom);

            var items_panel_template = new ItemsPanelTemplate();

            {
                var grid_factory = new FrameworkElementFactory(typeof(Grid));

                {
                    {
                        var col = new FrameworkElementFactory(typeof(ColumnDefinition));

                        col.SetValue(ColumnDefinition.WidthProperty, new GridLength(100));

                        grid_factory.AppendChild(col);
                    }

                    {
                        var col = new FrameworkElementFactory(typeof(ColumnDefinition));

                        col.SetValue(ColumnDefinition.WidthProperty, new GridLength(1, GridUnitType.Auto));

                        grid_factory.AppendChild(col);
                    }

                    {
                        var col = new FrameworkElementFactory(typeof(ColumnDefinition));

                        col.SetValue(ColumnDefinition.WidthProperty, new GridLength(1, GridUnitType.Star));

                        grid_factory.AppendChild(col);
                    }

                    {
                        var col = new FrameworkElementFactory(typeof(ColumnDefinition));

                        col.SetValue(ColumnDefinition.WidthProperty, new GridLength(1, GridUnitType.Auto));

                        grid_factory.AppendChild(col);
                    }

                    {
                        var col = new FrameworkElementFactory(typeof(ColumnDefinition));

                        col.SetValue(ColumnDefinition.WidthProperty, new GridLength(100));

                        grid_factory.AppendChild(col);
                    }
                }

                items_panel_template.VisualTree = grid_factory;
            }

            status_bar.ItemsPanel = items_panel_template;



            var text_block = new TextBlock();


            {
                var status_bar_item = new StatusBarItem();

                Grid.SetColumn(status_bar_item, 0);

                status_bar_item.Content = text_block;

                status_bar.Items.Add(status_bar_item);
            }

            {
                var separator = new Separator();

                Grid.SetColumn(separator, 1);

                status_bar.Items.Add(separator);
            }

            {
                var status_bar_item = new StatusBarItem();

                Grid.SetColumn(status_bar_item, 2);

                status_bar_item.Content = new TextBlock() { Text = "abc" };

                status_bar.Items.Add(status_bar_item);
            }

            {
                var separator = new Separator();

                Grid.SetColumn(separator, 3);

                status_bar.Items.Add(separator);
            }

            {
                var status_bar_item = new StatusBarItem();

                Grid.SetColumn(status_bar_item, 4);

                status_bar_item.Content = new ProgressBar() { Value = 50, Width = 90, Height = 16 };

                status_bar.Items.Add(status_bar_item);
            }

            {
                var text_box = new TextBox() { AcceptsReturn = true };

                text_box.SelectionChanged += (sender, e) => 
                {
                    var row = text_box.GetLineIndexFromCharacterIndex(text_box.CaretIndex);
                    var col = text_box.CaretIndex - text_box.GetCharacterIndexFromLineIndex(row);

                    text_block.Text = $"Line {row + 1}, Char {col + 1}";
                };

                dock_panel.Children.Add(text_box);
            }
        }
    }
}

Версия C # гораздо более многословна.Однако с помощью некоторых методов расширения его можно записать в свободном стиле, исключив промежуточные переменные:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var text_block = new TextBlock();

        Content = new DockPanel()

            .AddChildren(

                new StatusBar()
                    .SetDock(Dock.Bottom)
                    .SetItemsPanel(
                        new ItemsPanelTemplate()
                            .SetVisualTree(
                                new FrameworkElementFactory(typeof(Grid))
                                    .AppendChildren(
                                        new FrameworkElementFactory(typeof(ColumnDefinition))
                                            .SetValue_(ColumnDefinition.WidthProperty, new GridLength(100)),
                                        new FrameworkElementFactory(typeof(ColumnDefinition))
                                            .SetValue_(ColumnDefinition.WidthProperty, new GridLength(1, GridUnitType.Auto)),
                                        new FrameworkElementFactory(typeof(ColumnDefinition))
                                            .SetValue_(ColumnDefinition.WidthProperty, new GridLength(1, GridUnitType.Star)),
                                        new FrameworkElementFactory(typeof(ColumnDefinition))
                                            .SetValue_(ColumnDefinition.WidthProperty, new GridLength(1, GridUnitType.Auto)),
                                        new FrameworkElementFactory(typeof(ColumnDefinition))
                                            .SetValue_(ColumnDefinition.WidthProperty, new GridLength(100)))))
                    .AddItems(
                        new StatusBarItem() { Content = text_block }.SetColumn(0),
                        new Separator().SetColumn(1),
                        new StatusBarItem() { Content = new TextBlock() { Text = "abc" } }.SetColumn(2),
                        new Separator().SetColumn(3),
                        new StatusBarItem() { Content = new ProgressBar() { Value = 50, Width = 90, Height = 16 } }.SetColumn(4)),

                new TextBox() { AcceptsReturn = true }
                    .AddSelectionChanged(
                        (sender, e) =>
                        {
                            var box = sender as TextBox;

                            var row = box.GetLineIndexFromCharacterIndex(box.CaretIndex);
                            var col = box.CaretIndex - box.GetCharacterIndexFromLineIndex(row);

                            text_block.Text = $"Line {row + 1}, Char {col + 1}";
                        }));
    }
}

Вот используемые методы расширения:

public static class Extensions
{
    public static T SetDock<T>(this T element, Dock dock) where T : UIElement
    {
        DockPanel.SetDock(element, dock);

        return element;
    }

    public static T SetColumn<T>(this T element, int value) where T : UIElement
    {
        Grid.SetColumn(element, value);

        return element;
    }

    public static T SetValue_<T>(this T factory, DependencyProperty dp, object value) where T : FrameworkElementFactory
    {
        factory.SetValue(dp, value);

        return factory;
    }

    public static T AppendChildren<T>(this T factory, params FrameworkElementFactory[] children) where T : FrameworkElementFactory
    {
        foreach (var child in children)
            factory.AppendChild(child);

        return factory;
    }

    public static T SetVisualTree<T>(this T template, FrameworkElementFactory factory) where T : FrameworkTemplate
    {
        template.VisualTree = factory;

        return template;
    }

    public static T1 SetItemsPanel<T1,T2>(this T1 control, T2 template) where T1 : ItemsControl where T2 : ItemsPanelTemplate
    {
        control.ItemsPanel = template;

        return control;
    }

    public static T AddItems<T>(this T control, params object[] items) where T : ItemsControl
    {
        foreach (var item in items)
            control.Items.Add(item);

        return control;
    }

    public static T AddSelectionChanged<T>(this T obj, RoutedEventHandler handler) where T : TextBoxBase
    {
        obj.SelectionChanged += handler;

        return obj;
    }

    public static T1 AddChildren<T1>(this T1 panel, params UIElement[] elements) where T1 : Panel
    {
        foreach (var elt in elements)
            panel.Children.Add(elt);

        return panel;
    }

}
0 голосов
/ 25 сентября 2018

Если у вас все еще есть работа с элементами, вы должны взять следующий (расширенный) код:

Сначала нам нужен помощник, чтобы получить элемент:

// --------------------------------------------------------------------
// This function fetches the WrapPanel from oVisual.
private WrapPanel m_FetchWrapPanel (Visual oVisual)
{
  // WrapPanel to be returned
  WrapPanel oWrapPanel = null;
  // number of childs of oVisual
  int iNumberChilds = VisualTreeHelper.GetChildrenCount (oVisual);
  // and running through the childs
  int i = 0;
  while ( ( i < iNumberChilds ) && ( oWrapPanel == null ) )
  { // fetching visual
    Visual oVisualChild = 
      ( VisualTreeHelper.GetChild (oVisual, i) as Visual );
    if ( ( oVisualChild is WrapPanel ) is true )
    { // found
       oWrapPanel = ( oVisualChild as WrapPanel );
    }
    else
    { // checking the childs of oVisualChild 
      oWrapPanel = m_FetchWrapPanel (oVisualChild);
    };
    // checking next child
    i++;
  };
  // returning WrapPanel
  return (oWrapPanel);
}

Теперь мы создаем Панель (или что-то):

// --------------------------------------------------------------------
private void m_SettingTemplate ()
{
  // the online doc recommends to parse the template
  string xaml = 
    @"<ItemsPanelTemplate
          xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
          xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
        <WrapPanel ItemWidth=""150"" MaxWidth=""150""/>
      </ItemsPanelTemplate>";
  // assigning the template
  oMyListView.ItemsPanel = ( System.Windows.Markup.XamlReader.Parse (xaml) as ItemsPanelTemplate );
  // fetching the WrapPanel
  WrapPanel oWrapPanel = m_WrapPanelAusVisualHolen (oMyListView);
  Debug.Assert (oWrapPanel != null);
  if ( oWrapPanel != null )
  { // adjusting the size of the WrapPanel to the ListView
    Binding oBinding = new Binding ("ActualWidth");
    oBinding.Source = oMyListView;
    oWrapPanel.SetBinding (WrapPanel.MaxWidthProperty, oBinding);
  };
}
...