完成Grid示例
This commit is contained in:
29
RazorEngineTest/ExHelper.cs
Normal file
29
RazorEngineTest/ExHelper.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
namespace RazorEngineTest
|
||||||
|
{
|
||||||
|
public static class ExHelper
|
||||||
|
{
|
||||||
|
public static T? FindVisualChild<T>(this DependencyObject parent, string name = "") where T : DependencyObject
|
||||||
|
{
|
||||||
|
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
|
||||||
|
{
|
||||||
|
var child = VisualTreeHelper.GetChild(parent, i);
|
||||||
|
if (child is T result)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(name)) return result;
|
||||||
|
else if (result is FrameworkElement element && element.Name == name) return result;
|
||||||
|
}
|
||||||
|
var descendant = child.FindVisualChild<T>(name);
|
||||||
|
if (descendant != null) return descendant;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,22 +5,37 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:local="clr-namespace:RazorEngineTest"
|
xmlns:local="clr-namespace:RazorEngineTest"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Title="MainWindow" Height="450" Width="800">
|
Title="MainWindow" Height="500" Width="800">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Border BorderBrush="Green" BorderThickness="2" VerticalAlignment="Top" HorizontalAlignment="Left">
|
<Border BorderBrush="Green" BorderThickness="2" VerticalAlignment="Top" HorizontalAlignment="Left">
|
||||||
<local:MyControl Width="200" Height="40"/>
|
<local:MyControl Width="200" Height="40"/>
|
||||||
</Border>
|
</Border>
|
||||||
<Path Width="24" Height="24" Fill="Orange" Data="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-8.512 8.272l5.532 3.243-.686 1.162-5.533-3.243.687-1.162zm-1.456 3.113l6.185 1.739-.332 1.23-6.204-1.667.351-1.302zm-.672 2.813l6.498.65-.117 1.28-6.504-.586.123-1.344zm-.193 2.469h6.667v1.333h-6.667v-1.333zm8.833 3.333h-11v-7h1v6h9v-6h1v7zm-.852-8.704l-3.56-5.219 1.115-.76 3.559 5.219-1.114.76zm1.356-.841l-1.08-6.224 1.328-.231 1.082 6.224-1.33.231z"/>
|
<Path Width="24" Height="24" HorizontalAlignment="Left" Fill="Orange" Data="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-8.512 8.272l5.532 3.243-.686 1.162-5.533-3.243.687-1.162zm-1.456 3.113l6.185 1.739-.332 1.23-6.204-1.667.351-1.302zm-.672 2.813l6.498.65-.117 1.28-6.504-.586.123-1.344zm-.193 2.469h6.667v1.333h-6.667v-1.333zm8.833 3.333h-11v-7h1v6h9v-6h1v7zm-.852-8.704l-3.56-5.219 1.115-.76 3.559 5.219-1.114.76zm1.356-.841l-1.08-6.224 1.328-.231 1.082 6.224-1.33.231z"/>
|
||||||
<Button HorizontalAlignment="Right" VerticalAlignment="Top" Background="Transparent" BorderThickness="0" Foreground="Green">
|
<Button HorizontalAlignment="Right" VerticalAlignment="Top" Background="Transparent" BorderThickness="0" Foreground="Green" Click="Button_Click">
|
||||||
<Image Width="64" Height="64" HorizontalAlignment="Left">
|
<Image Width="64" Height="64" HorizontalAlignment="Left">
|
||||||
<Image.Source>
|
<Image.Source>
|
||||||
<DrawingImage>
|
<DrawingImage>
|
||||||
<DrawingImage.Drawing>
|
<DrawingImage.Drawing>
|
||||||
<GeometryDrawing Brush="{Binding RelativeSource={RelativeSource AncestorType={x:Type Button}},Path=Foreground}" Geometry="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-8.512 8.272l5.532 3.243-.686 1.162-5.533-3.243.687-1.162zm-1.456 3.113l6.185 1.739-.332 1.23-6.204-1.667.351-1.302zm-.672 2.813l6.498.65-.117 1.28-6.504-.586.123-1.344zm-.193 2.469h6.667v1.333h-6.667v-1.333zm8.833 3.333h-11v-7h1v6h9v-6h1v7zm-.852-8.704l-3.56-5.219 1.115-.76 3.559 5.219-1.114.76zm1.356-.841l-1.08-6.224 1.328-.231 1.082 6.224-1.33.231z"/>
|
<GeometryDrawing Brush="{Binding RelativeSource={RelativeSource AncestorType={x:Type Button}},Path=Foreground}"
|
||||||
|
Geometry="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-8.512 8.272l5.532 3.243-.686 1.162-5.533-3.243.687-1.162zm-1.456 3.113l6.185 1.739-.332 1.23-6.204-1.667.351-1.302zm-.672 2.813l6.498.65-.117 1.28-6.504-.586.123-1.344zm-.193 2.469h6.667v1.333h-6.667v-1.333zm8.833 3.333h-11v-7h1v6h9v-6h1v7zm-.852-8.704l-3.56-5.219 1.115-.76 3.559 5.219-1.114.76zm1.356-.841l-1.08-6.224 1.328-.231 1.082 6.224-1.33.231z"/>
|
||||||
</DrawingImage.Drawing>
|
</DrawingImage.Drawing>
|
||||||
</DrawingImage>
|
</DrawingImage>
|
||||||
</Image.Source>
|
</Image.Source>
|
||||||
</Image>
|
</Image>
|
||||||
</Button>
|
</Button>
|
||||||
|
<Border BorderBrush="Red" BorderThickness="2" Width="400" Height="400" HorizontalAlignment="Right" VerticalAlignment="Bottom">
|
||||||
|
<local:MyGrid x:Name="myGrid">
|
||||||
|
<local:MyGrid.RowDefinitions>
|
||||||
|
<RowDefinition/>
|
||||||
|
<RowDefinition/>
|
||||||
|
</local:MyGrid.RowDefinitions>
|
||||||
|
<local:MyGrid.ColDefinitions>
|
||||||
|
<ColumnDefinition/>
|
||||||
|
<ColumnDefinition/>
|
||||||
|
</local:MyGrid.ColDefinitions>
|
||||||
|
<Border Background="Green"/>
|
||||||
|
<Border Grid.RowSpan="2" Width="20" HorizontalAlignment="Right" Background="Blue" Opacity=".5"/>
|
||||||
|
</local:MyGrid>
|
||||||
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</Window>
|
||||||
|
|||||||
@@ -20,5 +20,13 @@ namespace RazorEngineTest
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Button_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Button c1 = new Button() { Content = "Button", Background = Brushes.Red, HorizontalAlignment = HorizontalAlignment.Stretch, VerticalAlignment = VerticalAlignment.Stretch };
|
||||||
|
Grid.SetColumn(c1, 1);
|
||||||
|
Grid.SetRow(c1, 1);
|
||||||
|
this.myGrid.Children.Add(c1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
155
RazorEngineTest/MyGrid.cs
Normal file
155
RazorEngineTest/MyGrid.cs
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Markup;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Animation;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
using System.Windows.Navigation;
|
||||||
|
using System.Windows.Shapes;
|
||||||
|
|
||||||
|
namespace RazorEngineTest
|
||||||
|
{
|
||||||
|
[ContentProperty("Children")]
|
||||||
|
[TemplatePart(Name = "PART_ChildrenContainer", Type = typeof(ItemsControl))]
|
||||||
|
public class MyGrid : Control
|
||||||
|
{
|
||||||
|
[AllowNull]
|
||||||
|
private ItemsControl PART_ChildrenContainer;
|
||||||
|
[AllowNull]
|
||||||
|
private Grid ChildrenContainer;
|
||||||
|
static MyGrid()
|
||||||
|
{
|
||||||
|
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyGrid), new FrameworkPropertyMetadata(typeof(MyGrid)));
|
||||||
|
}
|
||||||
|
public MyGrid()
|
||||||
|
{
|
||||||
|
this.Children = new UICollection();
|
||||||
|
this.RowDefinitions = new RowDefinitions();
|
||||||
|
this.ColDefinitions = new ColDefinitions();
|
||||||
|
}
|
||||||
|
public override void OnApplyTemplate()
|
||||||
|
{
|
||||||
|
base.OnApplyTemplate();
|
||||||
|
this.PART_ChildrenContainer = this.GetTemplateChild("PART_ChildrenContainer") as ItemsControl;
|
||||||
|
if (this.PART_ChildrenContainer != null)
|
||||||
|
this.PART_ChildrenContainer.Loaded += PART_ChildrenContainer_Loaded;
|
||||||
|
else throw new ArgumentNullException($"「{nameof(MyGrid)}」模版必须定义名称为「PART_ChildrenContainer」的「ItemsControl」类型子元素容器...");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PART_ChildrenContainer_Loaded(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
this.ChildrenContainer = this.PART_ChildrenContainer.FindVisualChild<Grid>("ChildrenContainer");
|
||||||
|
if (this.ChildrenContainer != null)
|
||||||
|
{
|
||||||
|
this.ChildrenContainer.ShowGridLines = DesignerProperties.GetIsInDesignMode(this);
|
||||||
|
|
||||||
|
this.ChildrenContainer.RowDefinitions.Clear();
|
||||||
|
foreach (var row in this.RowDefinitions) this.ChildrenContainer.RowDefinitions.Add(row);
|
||||||
|
|
||||||
|
this.ChildrenContainer.ColumnDefinitions.Clear();
|
||||||
|
foreach (var col in this.ColDefinitions) this.ChildrenContainer.ColumnDefinitions.Add(col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 子元素集合
|
||||||
|
/// </summary>
|
||||||
|
public UICollection Children
|
||||||
|
{
|
||||||
|
get { return (UICollection)GetValue(ChildrenProperty); }
|
||||||
|
set { SetValue(ChildrenProperty, value); }
|
||||||
|
}
|
||||||
|
public static readonly DependencyProperty ChildrenProperty =
|
||||||
|
DependencyProperty.Register("Children", typeof(UICollection), typeof(MyGrid), new PropertyMetadata(null,
|
||||||
|
(d, e) => (d as MyGrid)?.Children_PropertyChangedCallback(e)));
|
||||||
|
/// <summary>
|
||||||
|
/// 处理「MyGrid.Children」属性变更
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void Children_PropertyChangedCallback(DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.OldValue is UICollection oldUIColl) oldUIColl.CollectionChanged -= UICollection_CollectionChanged;
|
||||||
|
if (e.NewValue is UICollection newUIColl) newUIColl.CollectionChanged += UICollection_CollectionChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void UICollection_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
//TODO:这里可以处理逻辑树的父子级关系
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 行定义
|
||||||
|
/// </summary>
|
||||||
|
public RowDefinitions RowDefinitions
|
||||||
|
{
|
||||||
|
get { return (RowDefinitions)GetValue(RowDefinitionsProperty); }
|
||||||
|
protected internal set { SetValue(RowDefinitionsPropertyKey, value); }
|
||||||
|
}
|
||||||
|
public static readonly DependencyPropertyKey RowDefinitionsPropertyKey =
|
||||||
|
DependencyProperty.RegisterReadOnly("RowDefinitions", typeof(RowDefinitions), typeof(MyGrid), new PropertyMetadata(null,
|
||||||
|
(d, e) => (d as MyGrid)?.RowDefinitions_PropertyChangedCallback(e)));
|
||||||
|
public static readonly DependencyProperty RowDefinitionsProperty = RowDefinitionsPropertyKey.DependencyProperty;
|
||||||
|
/// <summary>
|
||||||
|
/// 处理「MyGrid.RowDefinitions」属性变更
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void RowDefinitions_PropertyChangedCallback(DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.OldValue is RowDefinitions oldRows) oldRows.CollectionChanged -= Rows_CollectionChanged;
|
||||||
|
if (e.NewValue is RowDefinitions newRows) newRows.CollectionChanged += Rows_CollectionChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Rows_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (this.ChildrenContainer != null)
|
||||||
|
{
|
||||||
|
this.ChildrenContainer.RowDefinitions.Clear();
|
||||||
|
foreach (var row in this.RowDefinitions)
|
||||||
|
this.ChildrenContainer.RowDefinitions.Add(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 列定义
|
||||||
|
/// </summary>
|
||||||
|
public ColDefinitions ColDefinitions
|
||||||
|
{
|
||||||
|
get { return (ColDefinitions)GetValue(ColDefinitionsProperty); }
|
||||||
|
protected internal set { SetValue(ColDefinitionsPropertyKey, value); }
|
||||||
|
}
|
||||||
|
public static readonly DependencyPropertyKey ColDefinitionsPropertyKey =
|
||||||
|
DependencyProperty.RegisterReadOnly("ColDefinitions", typeof(ColDefinitions), typeof(MyGrid), new PropertyMetadata(null,
|
||||||
|
(d, e) => (d as MyGrid)?.ColDefinitions_PropertyChangedCallback(e)));
|
||||||
|
public static readonly DependencyProperty ColDefinitionsProperty = ColDefinitionsPropertyKey.DependencyProperty;
|
||||||
|
/// <summary>
|
||||||
|
/// 处理「MyGrid.ColDefinitions」属性变更
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void ColDefinitions_PropertyChangedCallback(DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.OldValue is ColDefinitions oldCols) oldCols.CollectionChanged -= Cols_CollectionChanged;
|
||||||
|
if (e.NewValue is ColDefinitions newCols) newCols.CollectionChanged += Cols_CollectionChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Cols_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (this.ChildrenContainer != null)
|
||||||
|
{
|
||||||
|
this.ChildrenContainer.ColumnDefinitions.Clear();
|
||||||
|
foreach (var col in this.ColDefinitions)
|
||||||
|
this.ChildrenContainer.ColumnDefinitions.Add(col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[DefaultMember("Items")]
|
||||||
|
public class RowDefinitions : ObservableCollection<RowDefinition> { public RowDefinitions() { } }
|
||||||
|
[DefaultMember("Items")]
|
||||||
|
public class ColDefinitions : ObservableCollection<ColumnDefinition> { public ColDefinitions() { } }
|
||||||
|
}
|
||||||
@@ -95,4 +95,24 @@
|
|||||||
</Setter.Value>
|
</Setter.Value>
|
||||||
</Setter>
|
</Setter>
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="{x:Type local:MyGrid}">
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="{x:Type local:MyGrid}">
|
||||||
|
<Border Background="{TemplateBinding Background}"
|
||||||
|
BorderBrush="{TemplateBinding BorderBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}">
|
||||||
|
<ItemsControl x:Name="PART_ChildrenContainer" ItemsSource="{TemplateBinding Children}">
|
||||||
|
<ItemsControl.ItemsPanel>
|
||||||
|
<ItemsPanelTemplate>
|
||||||
|
<Grid x:Name="ChildrenContainer"/>
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</ItemsControl.ItemsPanel>
|
||||||
|
</ItemsControl>
|
||||||
|
</Border>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
|
|||||||
15
RazorEngineTest/UICollection.cs
Normal file
15
RazorEngineTest/UICollection.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
namespace RazorEngineTest
|
||||||
|
{
|
||||||
|
public class UICollection : ObservableCollection<UIElement>
|
||||||
|
{
|
||||||
|
public UICollection() { }
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user