c# - 为什么克隆的 UIElement 或 FrameworkElement 会丢失样式
问题描述
我正在尝试加载Grid
带有UIElement
s 和/或FrameworkElement
s 的 sStyle
和DataTrigger
s。
以下是按预期工作的简单本机 XAML;通过 3 种状态切换复选框为 Rectangle 提供三种不同的样式(见底部图片)。
<Grid
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:XamlVsLoad"
mc:Ignorable="d"
Height="450" Width="800">
<CheckBox Name="MyCheck" IsChecked="True" Content="Checkbox" IsThreeState="True" Margin="10,10,0,0" Width="200"/>
<Rectangle Height="100" Width="100" StrokeThickness="5" Margin="10,50,100,100">
<Rectangle.Style>
<Style TargetType="Rectangle">
<Setter Property="Fill" Value="White"/>
<Setter Property="Stroke" Value="Black"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=MyCheck, Path=IsChecked}" Value="True" >
<Setter Property="Fill" Value="Orange"/>
<Setter Property="Stroke" Value="Blue"/>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=MyCheck, Path=IsChecked}" Value="False" >
<Setter Property="Fill" Value="Blue"/>
<Setter Property="Stroke" Value="Orange"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
</Grid>
当我将相同的文本保存到文件并使用 XAML将其动态加载到Window
's 中时,它也可以工作,如下所示:Viewbox
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<DockPanel Grid.Column="0">
<DockPanel>
<Label Content="Native" DockPanel.Dock="Top" HorizontalAlignment="Center" Margin="10,10,10,10" />
<Viewbox Name="NativeViewbox" Height="auto" Width="200" DockPanel.Dock="Top"/>
<!-- Native Grid Omitted for brevity 3 uniquely named checkboxes -->
</Viewbox>
</DockPanel>
<DockPanel Grid.Column="1">
<DockPanel>
<Label Content="Dynamic" DockPanel.Dock="Top" HorizontalAlignment="Center" Margin="10,10,10,10" />
<Viewbox Name="DynamicViewbox" Height="auto" Width="200" DockPanel.Dock="Top"/>
</DockPanel>
</DockPanel>
<DockPanel Grid.Column="2">
<DockPanel>
<Label Content="Clone" DockPanel.Dock="Top" HorizontalAlignment="Center" Margin="10,10,10,10" />
<Viewbox Name="CloneViewbox" Height="auto" Width="200" DockPanel.Dock="Top" />
</DockPanel>
</DockPanel>
<DockPanel Grid.Column="3">
<DockPanel>
<Label Content="Saved" DockPanel.Dock="Top" HorizontalAlignment="Center" Margin="10,10,10,10" />
<Viewbox Name="SavedViewbox" Height="auto" Width="200" DockPanel.Dock="Top"/>
</DockPanel>
</DockPanel>
FrameworkElements
但是,如果我尝试将/UIElements
从一个/container复制/克隆/deepcopy(我尝试了几种不同的方法)Grid
到一个新的 /container,则该样式不再有效。以下是我目前加载和克隆它们的各种方式:
public partial class ReadCopy : Window {
public ReadCopy() {
InitializeComponent();
// test the dynamic load
Grid NativeXaml = ReadGrid("C:\\XamlFiles\\LoadXaml.xaml");
DynamicViewbox.Child = NativeXaml; // honors style
// test the Clone load
Grid CloneXaml = new Grid();
foreach (FrameworkElement fe in NativeXaml.Children) CloneXaml.Children.Add(Clone(fe));
CloneViewbox.Child = CloneXaml; // doesn't honor style
// test the save Clone and then load
StringBuilder outstr = new StringBuilder();
XmlWriterSettings settings = new XmlWriterSettings { Indent = true, OmitXmlDeclaration = true, IndentChars = " ", NewLineChars = "\r\n", NewLineHandling = NewLineHandling.Replace };
XamlDesignerSerializationManager dsm = new XamlDesignerSerializationManager(XmlWriter.Create(outstr, settings)) { XamlWriterMode = XamlWriterMode.Expression };
XamlWriter.Save(CloneXaml, dsm);
File.WriteAllText("C:\\XamlFiles\\SavedXaml.xaml", outstr.ToString());
Grid SavedXaml = ReadGrid("C:\\XamlFiles\\SavedXaml.xaml");
SavedViewbox.Child = SavedXaml; // honors style and triggers again...
}
public Grid ReadGrid(string fn) {
FileStream fs = new FileStream(fn, FileMode.Open);
return XamlReader.Load(fs) as Grid;
}
public FrameworkElement Clone(FrameworkElement it) {
FrameworkElement clone;
using (var stream = new MemoryStream()) {
XamlWriter.Save(it, stream);
stream.Seek(0, SeekOrigin.Begin);
clone = (FrameworkElement)XamlReader.Load(stream);
}
clone.Style = it.Style; // setting it or not has no effect
return clone;
}
}
开始的简单示例网格通过 XamlWriter.Save 克隆的 XAML 的输出:
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<CheckBox IsChecked="True" IsThreeState="True" Style="{x:Null}" Name="MyCheck" Width="200" Margin="10,10,0,0">Checkbox</CheckBox>
<Rectangle StrokeThickness="5" Width="100" Height="100" Margin="10,50,100,100">
<Rectangle.Style>
<Style TargetType="Rectangle">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsChecked, ElementName=MyCheck}" Value="True">
<Setter Property="Shape.Fill">
<Setter.Value>
<SolidColorBrush>#FFFFA500</SolidColorBrush>
</Setter.Value>
</Setter>
<Setter Property="Shape.Stroke">
<Setter.Value>
<SolidColorBrush>#FF0000FF</SolidColorBrush>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsChecked, ElementName=MyCheck}" Value="False">
<Setter Property="Shape.Fill">
<Setter.Value>
<SolidColorBrush>#FF0000FF</SolidColorBrush>
</Setter.Value>
</Setter>
<Setter Property="Shape.Stroke">
<Setter.Value>
<SolidColorBrush>#FFFFA500</SolidColorBrush>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
<Style.Resources>
<ResourceDictionary />
</Style.Resources>
<Setter Property="Shape.Fill">
<Setter.Value>
<SolidColorBrush>#FFFFFFFF</SolidColorBrush>
</Setter.Value>
</Setter>
<Setter Property="Shape.Stroke">
<Setter.Value>
<SolidColorBrush>#FF000000</SolidColorBrush>
</Setter.Value>
</Setter>
</Style>
</Rectangle.Style>
</Rectangle>
</Grid>
虽然我可以看到它重新格式化了,但我不明白为什么当我使用克隆Style
设置它时它不再起作用。Viewbox.Child
更令人困惑的是,加载克隆的保存文件然后工作。以下是所有四个(本机、动态、克隆、已保存克隆重新加载)的样子:
谁能解释如何通过复制/克隆正确保留样式?
解决方案
Style
on由Rectangle
触发CheckBox
。因此,Clone()
将无法单独加载子元素。要同时加载它们,请克隆它们的父级,即Grid
自身。我重现了您的问题,这对我有用:
Grid NativeXaml = ReadGrid();
DynamicViewbox.Child = NativeXaml;
Grid CloneXaml = (Grid)Clone(NativeXaml);
CloneViewbox.Child = CloneXaml;
推荐阅读
- c# - 将具有十六进制值的 JSON 反序列化为 sbyte 属性时,JsonConvert.DeserializeObject 引发异常
- ios - 我是否必须购买域才能运行我的应用程序,该应用程序在 AWS 服务器上使用 EC2 实例才能使用 HTTPS?
- php - 试图获取非对象错误的属性,而我应该取回一个对象?
- ios - SwiftUI:NavigationLink 目标视图的异构集合?
- c - 为什么我的 .exe 文件在执行后会崩溃
- python - Python Pandas 数据框移位在应用函数中不起作用
- excel - 需要识别某些单元格,然后将整行移动到另一个工作表
- mysql - 我想要最好的模式来存储反应
- java - 使用媒体播放器播放音频文件时出现问题
- javascript - 服务器在某些路由上抛出 500 错误