C# 条件XAML(WPF)
我试图创建一个用户控件,根据用户在Dependency属性中设置的模式,将用户控件更改为TextBlock和另一个TextBlock或TextBlock和TextBox。我知道依赖属性正在获取信息,但是当我试图设置正确的模板时,问题就出现了。由于某些原因,模板无法正确渲染 XAML:C# 条件XAML(WPF),c#,wpf,xaml,wpf-controls,C#,Wpf,Xaml,Wpf Controls,我试图创建一个用户控件,根据用户在Dependency属性中设置的模式,将用户控件更改为TextBlock和另一个TextBlock或TextBlock和TextBox。我知道依赖属性正在获取信息,但是当我试图设置正确的模板时,问题就出现了。由于某些原因,模板无法正确渲染 XAML: 代码隐藏: using System; using System.Windows; using System.Windows.Controls; namespace BookOrganizer {
代码隐藏:
using System;
using System.Windows;
using System.Windows.Controls;
namespace BookOrganizer
{
/// <summary>
/// Interaction logic for FlipBox.xaml
/// </summary>
public partial class FlipBox : UserControl
{
public static readonly DependencyProperty TitleProperty = DependencyProperty.Register(
"Title", typeof(String), typeof(FlipBox), new PropertyMetadata("nothing"));
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text", typeof(String), typeof(FlipBox), new PropertyMetadata("nothing"));
public static readonly DependencyProperty BoxModeProperty = DependencyProperty.Register(
"BoxMode", typeof(String), typeof(FlipBox), new PropertyMetadata("Box"));
public FlipBox()
{
InitializeComponent();
this.DataContext = this;
}
public String Title
{
get { return (String)this.GetValue(TitleProperty); }
set { this.SetValue(TitleProperty, value); }
}
public String Text
{
get { return (String)this.GetValue(TextProperty); }
set { this.SetValue(TextProperty, value); }
}
public String BoxMode
{
get { return (String)this.GetValue(BoxModeProperty); }
set { this.SetValue(BoxModeProperty, value); }
}
}
}
使用系统;
使用System.Windows;
使用System.Windows.Controls;
命名空间书籍管理器
{
///
///FlipBox.xaml的交互逻辑
///
公共部分类FlipBox:UserControl
{
公共静态只读DependencyProperty TitleProperty=DependencyProperty.Register(
“标题”、typeof(字符串)、typeof(动画框)、新属性ymetadata(“无”);
公共静态只读DependencyProperty TextProperty=DependencyProperty.Register(
“文本”、typeof(字符串)、typeof(动画框)、新属性ymatadata(“无”);
公共静态只读DependencyProperty BoxModeProperty=DependencyProperty.Register(
“BoxMode”、typeof(字符串)、typeof(FlipBox)、新属性元数据(“Box”);
公共动画框()
{
初始化组件();
this.DataContext=this;
}
公共字符串标题
{
获取{return(String)this.GetValue(TitleProperty);}
set{this.SetValue(TitleProperty,value);}
}
公共字符串文本
{
获取{return(String)this.GetValue(TextProperty);}
set{this.SetValue(TextProperty,value);}
}
公共字符串模式
{
获取{return(String)this.GetValue(BoxModeProperty);}
set{this.SetValue(BoxModeProperty,value);}
}
}
}
提前感谢。以下是如何创建条件控件的示例:
public class ConditionalControl : ContentControl
{
static ConditionalControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof (ConditionalControl), new FrameworkPropertyMetadata(typeof (ConditionalControl)));
}
#region Condition DP
public bool Condition
{
get { return (bool) GetValue(ConditionProperty); }
set { SetValue(ConditionProperty, value); }
}
public static readonly DependencyProperty ConditionProperty =
DependencyProperty.Register("Condition", typeof (bool), typeof (ConditionalControl), new UIPropertyMetadata(false));
#endregion
#region TrueTemplate DP
public DataTemplate TrueTemplate
{
get { return (DataTemplate) GetValue(TrueTemplateProperty); }
set { SetValue(TrueTemplateProperty, value); }
}
public static readonly DependencyProperty TrueTemplateProperty =
DependencyProperty.Register("TrueTemplate", typeof (DataTemplate), typeof (ConditionalControl), new UIPropertyMetadata(null));
#endregion
#region FalseTemplate DP
public DataTemplate FalseTemplate
{
get { return (DataTemplate) GetValue(FalseTemplateProperty); }
set { SetValue(FalseTemplateProperty, value); }
}
public static readonly DependencyProperty FalseTemplateProperty =
DependencyProperty.Register("FalseTemplate", typeof (DataTemplate), typeof (ConditionalControl), new UIPropertyMetadata(null));
#endregion
}
以下是您需要在项目中放入Themes/Generic.xaml
的样式:
<Style TargetType="{x:Type Controls:ConditionalControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Controls:ConditionalControl}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<ContentPresenter x:Name="FalseContentPresenter"
Content="{TemplateBinding DataContext}"
ContentTemplate="{TemplateBinding FalseTemplate}" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Condition"
Value="True">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Controls:ConditionalControl}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<ContentPresenter x:Name="TrueContentPresenter"
Content="{TemplateBinding DataContext}"
ContentTemplate="{TemplateBinding TrueTemplate}" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
您可能需要一个
IValueConverter
来将字符串更改为预期的控制模板。当作为裸字符串传递时,它不会查找资源键。另一种解决方案是使用样式
来改变可见性:
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Title}" />
<TextBox Text="{Binding Text}">
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding BoxMode}" Value="Box">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<TextBlock Text="{Binding Text}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding BoxMode}" Value="Box">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
您可以使用触发器设置模板。将UserControl中的StackPanel替换为以下内容
<StackPanel Orientation="Horizontal" Height="Auto" Width="Auto" >
<ContentControl>
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=BoxMode}" Value="Box">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<StackPanel Orientation="Horizontal" Height="Auto" Width="Auto">
<TextBlock Text="{Binding Path=Title}" Height="Auto" Width="Auto" />
<TextBlock Text="{Binding Path=Text}" Height="Auto" Width="Auto"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Path=BoxMode}" Value="Block">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Title}" Height="Auto" Width="Auto" />
<TextBox Text="{Binding Path=Text}" Height="Auto" Width="Auto" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</StackPanel>
定义“未正确渲染”。预期输出是什么?实际输出是什么?预期输出可能是一个文本块和另一个文本块,也可能是一个文本块和一个文本框。我得到的是一个盒子,里面有一个红色的圆圈和一个白色的X,或者什么都没有。基于我尝试运行它的方式。+1,尽管我确实认为绑定必须源于self,而不是(默认)DataContext。我在一个示例项目中尝试了这一点,并且绑定按原样工作。我非常喜欢这个解决方案,但我无法使用按钮使其工作。我还想在两个XAML设计之间切换。难道我不能使用你的精确XAML,但用按钮替换StackPanel吗?啊,我必须听从Jay的建议。在我的例子中,我将所有内容绑定到我自己(我使用的是基于按钮的自定义usercontrol),我必须对触发器使用的属性执行相同的操作。伟大的解决方案!
<StackPanel Orientation="Horizontal" Height="Auto" Width="Auto" >
<ContentControl>
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=BoxMode}" Value="Box">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<StackPanel Orientation="Horizontal" Height="Auto" Width="Auto">
<TextBlock Text="{Binding Path=Title}" Height="Auto" Width="Auto" />
<TextBlock Text="{Binding Path=Text}" Height="Auto" Width="Auto"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Path=BoxMode}" Value="Block">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Title}" Height="Auto" Width="Auto" />
<TextBox Text="{Binding Path=Text}" Height="Auto" Width="Auto" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</StackPanel>