WPF 确实令人惊叹,原因有很多,其中之一是它允许我们更改控件内的控件。例如,如果我们采用 ListBox。我们可以将面板从 StackPanel 更改为 WrapPanel,它仍然可以工作(我想显然 ListBox 和 WrapPanel 不共享任何类依赖项,因此它为什么工作)。
这是我对类依赖项的意思的示例。
public class Test1
{
public Test2 t;
public Test1(Test2 t)
{
this.t = t;
}
}
public class Test2
{
public string someStr;
}
现在可以像这样注入/插入实例:
Test2 test2 = new Test2();
test2.someStr = "Hello";
Test1 test1 = new Test1();
test1.t = test2;
或者可以像这样插入实例:
Test2 test2 = new Test2();
test2.someStr = "Hello";
Test1 test1 = new Test1(test2);
几乎没有其他方法可以做到这一点,但我希望你们现在明白这一点。
所以现在在我们知道如何注入实例之后,让我们尝试使用以下示例在 WPF 中这样做:
我有一个自定义控件。我的 CustomControl 有点复杂,因为它有行和列。此外,CustomControl 不是从 DataGrid 派生的。事实上,它是从 ItemsControl 派生的。
正如我提到的,它有列和行,或者更准确地说,行需要了解列。那就是我想在一行中插入列实例的地方。我如何在 WPF 中做到这一点?
这是我的问题的一个简单的简单示例:
假设 CustomControl 的 VisualTree 如下所示:
CustomControl
+ Grid
+ Border
+ ContentPresenter
+ Headers
+ DockPanel
+ Border
+ ContentPresenter
+ Rows
如您所见,行远离标题,我想在不找到标题的情况下获取/插入标题的实例到行。
Rows 和 Headers 类如下所示:
class Row : ContentControl
{
List<Column> Headers;
...
}
class Headers : ContentControl
{
List<Column> Cols = new List<Column>()
public Headers()
{
this.Cols.Add(...);
this.Cols.Add(...);
}
...
}
问题是如何做这样的事情:
this.rows.Headers = columns.Cols;
我在互联网上搜索过,很多人建议我让该行使用 VisualTreeHelper,然后沿着树向上移动以找到 Cols。事实上,我尝试这样做,并且在使用性能分析器工具监视了我的 CustomControl 之后,我认为这正是每一行都在树中查找最耗时的标题的步骤。因此,让我们不要使用 VisualTreeHelper,而是像我在上面的 Test1 和 Test2 示例中描述的那样使用注入。
有什么建议么?这可能有一个模式吗?
已编辑:@Benjamin。在 OnApplyTemplate 中使用 RedSlider = GetTemplateChild("RedSlider") 是一个很好的解决方案,但它对我不起作用,因为我的情况更复杂。就我而言,我真的需要以某种方式插入实例。这是我无法在 OnAppyTemplate 方法中使用 GetTemplateChild 的示例。
这是滑块控件。
class CustomSliders : ContentControl
{
}
CustomSlider 的样式如下所示:
<Style x:Key="mySliders" TargetType="{x:Type local:CustomSliders}">
<Style.Setter Property="Template">
<ControlTemplate TargetType="{x:Type local:CustomSliders}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Slider x:Name="PART_RedSLider" />
<Slider x:Name="PART_GreenSlider" Grid.Row="1"/>
<Slider x:Name="PART_BlueSlider" Grid.Row="2"/>
<Slider x:Name="PART_AlphaSlider" Grid.Row="3"/>
</Grid>
</ContentTemplate>
</Style>
这是我的CustomControl 的ControlTemplate,名为ColorPicker。
<ContentTemplate TargetType="Picker">
<DockPanel>
<ContentControl DockPanel.Dock="Left" Style="{StaticResource mySliders}"/>
<Rectangle x:Name="PART_ColorPresenter"
DockPanel.Dock="Right"
Margin="5"/>
</Grid>
</ControlTemplate>
在此示例中,将在 ColorPicker 的 OnApplyTemplate 内执行的 GetTemplatedChild 方法将不起作用,因为它找不到位于 CustomSliders 内的 PART_RedSLider。
GetTemplateChild 无法在 VisualTree 中找到所有内容。
因为 GetTemplatedChild 无法解决这个复杂的模板结构,所以很多人建议我使用 VisualTreeHelper.Find() 反复地在树上或下旅行。尽管就像我在问题中解释的那样,我不想使用递归方式。我想插入实例..