我的应用程序包含TabControl
个TabItem
个托管自定义UserControl
的代码:
<TabControl>
<TabItem Header="UC_1 and UC_2">
<StackPanel>
<local:UC_1/>
<Separator/>
<local:UC_2/>
</StackPanel>
</TabItem>
<TabItem Header="UC_3">
<local:UC_3/>
</TabItem>
<TabItem Header="UC_4">
<local:UC_3/>
</TabItem>
</TabControl>
UserControl
对它们有许多不同的控制,如下所示:
<ScrollViewer>
<StackPanel>
<DockPanel>
<TextBlock Text="Surname"/>
<Border>
<TextBox Text="{Binding Model.Surname}" />
</Border>
</DockPanel>
<DockPanel>
<TextBlock Text="Firstname" />
<Border>
<TextBox Text="{Binding Model.Firstname}" />
</Border>
</DockPanel>
</StackPanel>
</ScrollViewer>
现在我想将整个TabControl
设置为ReadOnly
,具体取决于模型中的属性,因此用户仍然可以阅读但不能编辑控件的内容。
很遗憾,IsReadOnly
不是TabControl
的属性,也不是TabItem
或UserControl
的属性。所以我决定改用IsEnabled
- 属性。
但是,如果我禁用整个TabControl
,则用户将无法在TabItems
之间切换以读取数据,因为如果禁用这些数据则无法点击(这似乎是合法的,鉴于IsEnabled
- 属性的含义。
所以,为了实现我的&#34;已禁用但仍然可点击的&#34; - TabItem
,我尝试在Style
内设置DataTrigger
TabControl
的资源,因此请停用UserControl
内的TabItem
而不是整个TabControl
或TabItem
:
<TabControl.Resources>
<Style TargetType="{x:Type UserControl}">
<Style.Triggers>
<DataTrigger Binding="{Binding Model.TCEnabledProperty}" Value="9">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TabControl.Resources>
但这不起作用。
所以我改变了
<Style TargetType="{x:Type UserControl}">
到
<Style TargetType="{x:Type StackPanel}">
突然我得到了预期的行为但(当然)仅如果给定的UserControl
有StackPanel
托管所有其他控件,所有这些UserControl
的情况并非如此。
为什么Style
适用于TargetType = StackPanel
而不适用于TargetType = UserControl
?我不明白我可以访问内的 UserControl
而不是UserControl
本身。
如果没有其他选项,我只会向StackPanel
添加一个包裹UserControl
已经没有,但为了好奇,我想了解整个我在这里遇到的行为......
答案 0 :(得分:1)
为什么不单独绑定每个TabItem的内容IsEnabled属性?
<TabItem Header="UC_1 and UC_2">
<StackPanel IsEnabled="{Binding ...}"/> <!-- use converter if you can't create property called 'IsTCEnabled' in viewmodel -->
<local:UC_1 />
<Separator />
<local:UC_2 />
</StackPanel>
</TabItem>
<TabItem Header="UC_3">
<local:UC_3 IsEnabled="{Binding ...}"/>
</TabItem>
<TabItem Header="UC_4">
<local:UC_3 IsEnabled="{Binding ...}"/>
</TabItem>
您也可以创建样式以避免重复绑定:
<Style x:Key="TabContent" TargetType="FrameworkElement">
<Setter Property="IsEnabled" Value="{Binding }" />
</Style>
<TabItem Header="UC_1 and UC_2">
<StackPanel Style="{StaticResource TabContent}" />
<local:UC_1 />
<Separator />
<local:UC_2 />
</StackPanel>
</TabItem>
<TabItem Header="UC_3">
<local:UC_3 Style="{StaticResource TabContent}" />
</TabItem>
<TabItem Header="UC_4">
<local:UC_3 Style="{StaticResource TabContent}" />
</TabItem>
编辑:回答您的问题
它很简单。 StackPanel样式有效,因为您已将StackPanel添加到第一个选项卡。 UserControl不起作用,因为您已将UC_1和UC_2添加到第二个选项卡。隐式样式不适用于继承的控件。 TargetType必须与元素的类型完全匹配。为什么Style适用于TargetType = StackPanel但不适用于 TargetType = UserControl?
答案 1 :(得分:0)
将IsReadOnly
依赖项属性添加到UserControl
:
<ScrollViewer>
<StackPanel>
<DockPanel>
<TextBlock Text="Surname"/>
<Border>
<TextBox Text="{Binding Model.Surname}" />
</Border>
</DockPanel>
<DockPanel>
<TextBlock Text="Firstname" />
<Border>
<TextBlock x:Name="textBlock" Text="{Binding Model.Firstname}" />
<TextBox x:Name="textBox" Text="{Binding Model.Firstname}" />
</Border>
</DockPanel>
</StackPanel>
</ScrollViewer>
和代码(可以使用绑定和转换器完成,x:Name
- 方式只是更快的演示方式):
public bool IsReadOnly
{
get { return (bool)GetValue(IsReadOnlyProperty); }
set { SetValue(IsReadOnlyProperty, value); }
}
public static readonly DependencyProperty IsReadOnlyProperty =
DependencyProperty.Register("IsReadOnly", typeof(bool), typeof(MyUserControl), new PropertyMetadata(false, (d, e) =>
{
var userControl = (MyUserControl)s;
var value = (bool)e.NewValue;
userControl.textBlock.Visible = value ? Visibility.Visible : Visibility.Hidden;
userControl.textBox.Visible = !value ? Visibility.Visible : Visibility.Hidden;
}));
然后你应该可以在标签页中设置它:
<TabItem Header="MyUserControl">
<local:MyUserControl IsReadOnly="{Binding SomeBinding}"/>
</TabItem>
答案 2 :(得分:0)
修改强>
Liero为这个问题提供了更好的解决方案。我还在离开我的答案,因为当我想知道为什么我无法在我的视图中将Style
应用于TargetType=UserControl
时,我将基类与具体对象混淆,下面的文字可能帮助他人了解差异。
对Sinatr回答的评论中的讨论引导我访问stackoverflow上的另一篇文章,在那里我找到了the solution to the question。
为什么setter不适用于TargetType=UserControl
?
简短的回答是:
Style
只能应用于具体对象。
UserControl
只是一个类,不是具体对象。具体对象是<local:UC_1/>
。
另一方面,StackPanels
肯定是具体对象,即使它们是在UserControl
内的可视树下进一步托管,因此也是{{} 1}}可以应用。
此外,如果Style
中的对象尚未设置Style
,则Style
似乎只能自上而下设置。{
我试图从上到下设置的任何UserControl
只会被视觉树内嵌套的Style
再次覆盖(最后Style
次胜利)。
这适用于Style
为Style
中的对象设置的任何ResourceDirectory
。