如何从子元素条件的父元素DataTrigger
问题描述:
试图找到解决以下问题的方法。如何从子元素条件的父元素DataTrigger
我的目标是: 如果Button中的某个子元素不包含文本,则禁用父按钮。
那么,到底是什么我试图做:
创建一个按钮:
<Button Style="{StaticResource ButtonStyle}" >
<TextBlock>
<Run Name="TxtElement1" Text=""/>
</TextBlock>
</Button>
<Button Style="{StaticResource ButtonStyle}" >
<TextBlock>
<Run Name="TxtElement2" Text="some text 1"/>
</TextBlock>
</Button>
<Button Style="{StaticResource ButtonStyle}" >
<TextBlock>
<Run Name="TxtElement3" Text="some text 2"/>
</TextBlock>
</Button>
现在创建一个风格的触发器:
<Style x:Key="ButtonStyle" TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=TxtElement1, Path=Text}" Value="">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=TxtElement2, Path=Text}" Value="">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=TxtElement3, Path=Text}" Value="">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
所以,结果我得到: 所有ToggleButtons被禁用。 但我需要只禁用按钮时,属性文本中运行子元素为空
也许我使用根本上错误的方法..感谢您的任何关注。
答
我建议不要让事情变得复杂。在设置数据之前,样式应用于按钮。直接将VMSource绑定到Button的内容属性。然后,由于加载的文本被更新后才发射使用Loaded事件做一些操作(在这种情况下启用/禁用。见下面剪断。
<Button Loaded="Button_Loaded" Content="" />
<Button Loaded="Button_Loaded" Content="some text 1" />
<Button Loaded="Button_Loaded" Content="some text 2"/>
下面将是你Button_Loaded事件。
private void Button_Loaded(object sender, RoutedEventArgs e)
{
Button _button = (Button)sender;
if (string.IsNullOrEmpty(_button.Content.ToString()))
_button.IsEnabled = false;
}
,你总会看到按钮被禁用,因为没有内容。
好运。
答
哇人... ...你真的得到了我的大脑烟熏。
我来到了一个非常难看的解决方案,那可能会解决你顽固的愿望,使用Run
。
XAML
<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self} , Path=Content, Converter={StaticResource Converter}, UpdateSourceTrigger=PropertyChanged}" Value="True">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
转换
public class MyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) return true; //No Content at all
var block = value as TextBlock;
if (block != null)
{
block.Loaded += (sender, args) => //Inlines are only availilable if Control has loaded
{
var loadedBlock = sender as TextBlock;
var inlineCount = loadedBlock.Inlines.Count == 0;
if (!inlineCount)
{
var runs = loadedBlock.Inlines.OfType<Run>();
foreach (var run in runs.Where(run => !string.IsNullOrEmpty(run.Text)))
{
(loadedBlock.Parent as Button).IsEnabled = true;
}
}
};
return string.IsNullOrEmpty(block.Text);
}
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
用法
<Button Content="Click me" Width="80" Height="20" Style="{StaticResource ButtonStyle}"/>
<Button Width="80" Height="20" Style="{StaticResource ButtonStyle}"/>
<Button Width="80" Height="20" Style="{StaticResource ButtonStyle}">
<TextBlock Foreground="Red">
<Run Name="TxtElement3" Text="some text 2"/>
</TextBlock>
</Button>
<Button Width="80" Height="20" Style="{StaticResource ButtonStyle}" >
<TextBlock>
<Run Text=""/>
</TextBlock>
</Button>
<Button Width="80" Height="20" Style="{StaticResource ButtonStyle}" >
<TextBlock>
<Run Text=""/>
<Run Text="Some other Text"></Run>
</TextBlock>
</Button>
IMPOPRTANT
我高度评价!建议您到不使用此解决方案(即使它有效)。 取而代之的是使用按钮的内容,如果你只有纯文本,就把你的东西放在那里。
Tbh,这完全没有意义......为什么你甚至会像这样设计你的按钮?使用按钮的“内容”,并进行自我约束 – lokusking
在我的情况下,我使用按钮内容的几个来源。看起来像:' ' –
好吧。对你有好处。不改变它真的很奇怪的事实,这不会工作。样式在**按钮之前定义**,因此对按钮的内容没有任何了解(对于一些简单的文本,您应该真的使用它)。解决方法可能是“ControlTemplate”或“行为”或“代码隐藏”。但是对于普通的XAML,你会有一段糟糕的时光 – lokusking