【问题标题】:How to DataTrigger for Parent element from child element condition如何从子元素条件 DataTrigger 为父元素
【发布时间】:2018-06-02 16:42:05
【问题描述】:

试图找到解决以下问题的方法。

我的目标是: 如果 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>

所以,我得到的结果是:所有切换按钮都被禁用。 但是当运行子元素中的属性文本为空时,我只需要禁用按钮

也许我使用了完全错误的方法.. 感谢您的关注。

【问题讨论】:

  • Tbh,这完全没有意义......你为什么要这样设计你的按钮?使用按钮的Content 并进行自绑定
  • 就我而言,我使用的按钮内容来源很少。看起来像:&lt;TextBlock &gt; &lt;Run Text="Some text"/&gt; &lt;Run Name="TxtElement3" Text="{Binding SomeTextFromVM}"/&gt; &lt;/TextBlock&gt;
  • 好的。对你有益。不会改变它真的很奇怪而且这不起作用的事实。样式是在您的按钮之前定义的,因此不了解按钮的内容(您应该真正将其用于一些简单的文本)。解决方法可能是ControlTemplate 或 Behavior 或 CodeBehind。但是使用普通的 XAML,你会度过一段糟糕的时光
  • 当然是在我真正的 XAML Style 之前写的 Buttons。很抱歉造成混淆。您可以透露一些我如何使用 ControlTemplate 来解决我的问题的细节?我将不胜感激

标签: wpf xaml


【解决方案1】:

我建议不要让事情变得复杂。在设置数据之前将样式应用于按钮。将您的 VMSource 直接绑定到 Button 的 Content 属性。然后使用 Loaded Event 执行一些操作(在这种情况下启用/禁用。请参阅下面的片段。

<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;
}

由于 Loaded 仅在文本更新后触发,因此您将始终看到按钮被禁用,因为没有内容。

祝你好运。

【讨论】:

    【解决方案2】:

    哇,伙计...你真的让我的大脑发烟了。

    我想出了一个非常丑陋的解决方案,它可能会满足您使用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>
    

    重要

    我高度!建议您不要使用此解决方案(即使它有效)。 而是使用按钮的内容,如果您只有纯文本,只需将您的内容放在那里。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-13
      • 2020-08-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多