我需要根据标志以不同的方式在usercontrol中显示数据。
为了达到这个目的,我尝试了以下方法,但在主视图中使用此控件时没有显示任何内容。
<UserControl DataContext="**self**">
<UserControl.Resources>
<DataTemplate x:Key="mouseInputTemplate">
<TextBlock HorizontalAlignment="Center"><Run Text="{Binding Text}" /></TextBlock>
</DataTemplate>
<DataTemplate x:Key="touchInputTemplate">
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Image Source="{Binding ImageUri}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Width="{Binding ImageWidth}" Height="{Binding ImageHeight}" />
<TextBlock HorizontalAlignment="Center"><Run Text="{Binding Text}" /></TextBlock>
</StackPanel>
</DataTemplate>
<local:InputModeDataTemplateSelector x:Key="inputModeTemplateSelector"
MouseInputModeTemplate="{StaticResource mouseInputTemplate}"
TouchInputModeTemplate="{StaticResource touchInputTemplate}" />
</UserControl.Resources>
<ContentControl HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" VerticalAlignment="Stretch"
VerticalContentAlignment="Stretch" ContentTemplateSelector="{StaticResource inputModeTemplateSelector}" />
</UserControl>
我做错了什么? 有没有更好的方法来实现这一目标?
答案 0 :(得分:1)
您的ContentPresenter想法是使用DataTemplateSelector执行此操作的正确方法,我应该自己考虑一下。
但是,这是另一种方法,与我的第一个答案不同,它实际上解决了你所遇到的所有问题:
XAML(实际上,Style可能会在单独的ResourceDictionary中定义):
<Window
x:Class="TestApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestApplication"
xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
Title="MainWindow" Height="350" Width="525"
>
<Window.Resources>
<Style TargetType="local:TestControl">
<Setter Property="Background" Value="Gainsboro" />
<Style.Triggers>
<!-- The 0 value for the InputMode enum is Mouse, so this will be the default. -->
<Trigger Property="InputMode" Value="Mouse">
<Setter Property="Background" Value="Wheat" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:TestControl}">
<Grid Background="{TemplateBinding Background}">
<TextBlock HorizontalAlignment="Center"><Run Text="{TemplateBinding Text}" /></TextBlock>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="InputMode" Value="Touch">
<Setter Property="Background" Value="LightSkyBlue" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:TestControl}">
<Grid Background="{TemplateBinding Background}">
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Image
Source="{TemplateBinding ImageUri}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Width="{TemplateBinding ImageWidth}"
Height="{TemplateBinding ImageHeight}"
/>
<TextBlock HorizontalAlignment="Center"><Run Text="{TemplateBinding Text}" /></TextBlock>
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<local:TestControl
ImageHeight="100"
ImageWidth="100"
Text="This is the test control"
ImageUri="http://www.optimizeagency.com/wp-content/uploads/2015/09/GoogleLogo.jpg"
/>
</Grid>
</Window>
C#:
using System;
using System.Windows;
using System.Windows.Controls;
namespace TestApplication
{
class TestControl : Control
{
public TestControl()
{
// If input mode may change at runtime, you'll need an event that fires when that
// happens and updates this property.
// UIUtilities.GetInputMode() is just a stub in this example.
InputMode = UIUtilities.GetInputMode();
}
#region InputMode Property
public InputMode InputMode
{
get { return (InputMode)GetValue(InputModeProperty); }
set { SetValue(InputModeProperty, value); }
}
public static readonly DependencyProperty InputModeProperty =
DependencyProperty.Register("InputMode", typeof(InputMode), typeof(TestControl),
new PropertyMetadata(InputMode.Mouse));
#endregion InputMode Property
#region Text Property
public String Text
{
get { return (String)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(String), typeof(TestControl),
new PropertyMetadata(null));
#endregion Text Property
#region ImageUri Property
// The TemplateBinding in the template can't coerce a string to an
// ImageSource, so we have to make that happen elsewhere.
public ImageSource ImageUri
{
get { return (ImageSource)GetValue(ImageUriProperty); }
set { SetValue(ImageUriProperty, value); }
}
public static readonly DependencyProperty ImageUriProperty =
DependencyProperty.Register("ImageUri", typeof(ImageSource), typeof(TestControl),
new PropertyMetadata(null));
#endregion ImageUri Property
#region ImageHeight Property
public float ImageHeight
{
get { return (float)GetValue(ImageHeightProperty); }
set { SetValue(ImageHeightProperty, value); }
}
public static readonly DependencyProperty ImageHeightProperty =
DependencyProperty.Register("ImageHeight", typeof(float), typeof(TestControl),
new PropertyMetadata(float.NaN));
#endregion ImageHeight Property
#region ImageWidth Property
public float ImageWidth
{
get { return (float)GetValue(ImageWidthProperty); }
set { SetValue(ImageWidthProperty, value); }
}
public static readonly DependencyProperty ImageWidthProperty =
DependencyProperty.Register("ImageWidth", typeof(float), typeof(TestControl),
new PropertyMetadata(float.NaN));
#endregion ImageWidth Property
}
#region This stuff belongs in a different file
public static class UIUtilities
{
public static InputMode GetInputMode()
{
// Here you'd do whatever you're already doing to detect the input mode
return InputMode.Touch;
}
}
public enum InputMode
{
Mouse,
Touch
}
#endregion This stuff belongs in a different file
}
答案 1 :(得分:1)
感谢EdPlunkett和更多研究我发现它更好
在这里使用ContentPresenter
而不是像这样绑定DataContext=this
绑定(就像编写UserControl时建议的那样)
DataContext="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type yourType}}}"
代码:
<UserControl.Resources>
<DataTemplate x:Key="touchInputTemplate">
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Image Source="{Binding ImageUri}" Width="64" Height="64" />
<TextBlock HorizontalAlignment="Center" Text="{Binding Text}" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="mouseInputTemplate">
<TextBlock HorizontalAlignment="Center" Text="{Binding Text}" />
</DataTemplate>
<local:InputModeDataTemplateSelector x:Key="inputModeTemplateSelector"
MouseInputModeTemplate="{StaticResource mouseInputTemplate}"
TouchInputModeTemplate="{StaticResource touchInputTemplate}" />
</UserControl.Resources>
<Grid DataContext="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type yourType}}}">
<ContentPresenter Content="{Binding}" ContentTemplateSelector="{StaticResource inputModeTemplateSelector}">
</Grid>