WPFは多くの理由で本当に素晴らしいですが、その1つは、コントロール内のコントロールを変更できることです。例として、リストボックスを取り上げます。パネルを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は行と列があるため、少し複雑です。さらに、CustomControlはDataGridから派生していません。実際、これはItemsControlから派生しています。
私が述べたように、それは列と行を持っています、より正確には、行は列について知る必要があります。ここで、列のインスタンスを行に挿入します。WPFでそれを行うにはどうすればよいですか?
これが私の問題の簡単でわかりやすい例です。
CustomControlのVisualTreeが次のようになっているとします。
CustomControl
+ Grid
+ Border
+ ContentPresenter
+ Headers
+ DockPanel
+ Border
+ ContentPresenter
+ Rows
ご覧のとおり、行はヘッダーから遠く離れているので、ヘッダーを見つけずに行へのヘッダーのインスタンスを取得/挿入したいと思います。
行とヘッダーのクラスは次のようになります。
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を使用させてから、ツリーを上に移動してColを見つけるように提案しました。実際、私はそうしようとしましたが、パフォーマンスプロファイラーツールで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>
そして、これはColorPickerと呼ばれる私のCustomControlのControlTemplateです。
<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()を使用してツリーを上下に移動することを提案しています。質問で説明したように、私は再帰的な方法を使いたくありません。インスタンスを挿入したい。