我在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();
但悲惨地失败了。有什么帮助吗?
背景 我只知道运行时网格列和行的数量。
答案 0 :(得分:4)
您需要创建ItemsPanelTemplate
并将其VisualTree
设置为FrameworkElementFactory
(已弃用),以创建Grid
,或使用{{3}向XamlReader
指定模板的XAML字符串。
parse包含两种方法的用法示例(虽然是针对不同的模板属性)。
This question概述了一种在运行时操作面板的更简单方法。
答案 1 :(得分:3)
您可以在后面的代码中创建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;
}
现在将此模板添加到Listbox ItemsPanel中:
MyListBox.ItemsPanel = GetItemsPanelTemplate();
这对我来说很好。希望这会有所帮助。
保持编码......:)
答案 2 :(得分:0)
如果仍然需要处理一些元素,则应采用以下(扩展的)代码:
首先,我们需要一个助手来获取元素:
// --------------------------------------------------------------------
// 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);
};
}
答案 3 :(得分:0)
这是一个基于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}";
}
}
}
这是一个带有状态栏的简单文本编辑器:
以下是带有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;
}
}