1) Ответ - да.Например, если вы хотите определить шаблон в вашем окне для простой строки
public MainWindow()
{
InitializeComponent();
DataTemplate template = new DataTemplate(typeof(string));
FrameworkElementFactory borderFactory = new FrameworkElementFactory(typeof(Border));
borderFactory.SetValue(Border.PaddingProperty, new Thickness(1));
borderFactory.SetValue(Border.BorderThicknessProperty, new Thickness(1));
borderFactory.SetValue(Border.BorderBrushProperty, Brushes.Red);
FrameworkElementFactory textFactory = new FrameworkElementFactory(typeof(TextBlock));
textFactory.SetBinding(TextBlock.TextProperty, new Binding
{
Mode = BindingMode.OneWay
});
borderFactory.AppendChild(textFactory);
template.VisualTree = borderFactory;
myControl.ContentTemplate = template;
}
И в окне вы просто поместите что-то вроде
<ContentControl x:Name="myControl" Content="Test text" Margin="10"/>
Ваш элемент управления контентом будет отображать строкуокружен красной каймой.Но, как вы видите, очень сложно определить ваши шаблоны таким образом.Единственный сценарий, в котором я мог бы представить себе такой подход, это для каких-то процедурно сгенерированных шаблонов.
Другой способ - сгенерировать строку для шаблона и затем загрузить ее с помощью XamlReader:
string xaml = "<Ellipse Name=\"EllipseAdded\" Width=\"300.5\" Height=\"200\"
Fill=\"Red\" xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"/>";
object ellipse = XamlReader.Load(xaml);
2) Я не вижу необходимости создавать шаблоны в коде позади.Например, для такой структуры данных:
public class User
{
public string Name { get; set; }
public User Friend { get; set; }
}
public class RootNode
{
public string Title { get; set; }
public User User { get; set; }
public List<Node> Nodes { get; set; }
}
public class Node
{
public string Title { get; set; }
public List<SubNode> SubNodes { get; set; }
}
public class SubNode
{
public string Title { get; set; }
}
Вы можете определить этот тип шаблона:
<Window
...
Title="MainWindow" Height="350" Width="525" >
<Window.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:RootNode}" ItemsSource="{Binding Nodes}">
<StackPanel x:Name="spContainer" Orientation="Horizontal">
<TextBlock Text="{Binding Title}"/>
<TextBlock Text="{Binding User.Friend.Friend.Name}"/>
</StackPanel>
<HierarchicalDataTemplate.Triggers>
<DataTrigger Binding="{Binding User}" Value="{x:Null}">
<Setter TargetName="spContainer" Property="Background" Value="Yellow"/>
</DataTrigger>
</HierarchicalDataTemplate.Triggers>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:Node}" ItemsSource="{Binding SubNodes}">
<TextBlock Text="{Binding Title}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:SubNode}" ItemsSource="{Binding Nodes}">
<TextBlock Text="{Binding Title}"/>
</HierarchicalDataTemplate>
</Window.Resources>
<Grid>
<TreeView ItemsSource="{Binding RootNodes}"/>
</Grid>
</Window>
Как видите, вы можете определить шаблон по типу данных, вы можететакже используйте триггеры для изменения поведения в определенных случаях, вы также можете использовать сом-конвертеры привязки ...
3) Вы можете привязать к вложенным свойствам так же, как к обычным:
<TextBlock Text="{Binding User.Friend.Friend.Name}"/>
Однако в некоторых случаях может произойти сбой более двух привязок уровня (не удается разрешить или обновить при изменении свойства, ...)