【问题标题】:Multibinding for tooltip and ContentTemplateSelector工具提示和 ContentTemplateSelector 的多重绑定
【发布时间】:2018-09-19 12:37:34
【问题描述】:

如何将工具提示和 ContentTemplateSelector 多重绑定到两个或多个属性?这是框架代码:

<Grid>
     <Grid Definitions>
      <Content Control
          **Line A** *ToolTip*//Want to bind to the same two properties as in the Text Box below and invoke the converter
          **Line B** *ContentTemplateSelector*  //Want to bind to the same two properties as in the Text Box below and invoke the converter
       />  
       **Line C** <TextBlock
          <TextBlock.Text>
                        <MultiBinding Converter="{StaticResource CountToStringConverter}">
                            <Binding Path="Property1"/>
                            <Binding Path="Property2" />
                        </MultiBinding>
            </TextBlock.Text>
        </TextBlock>
<Grid Ends>

看起来我不能使用我用于文本块的 MultiBinding 方式。我的 ContentTemplateSelector 转换器继承了 DataTemplateSelector 控件。感谢任何解决方法/输入。此外,我无法为工具提示使用类似的多重绑定声明

【问题讨论】:

    标签: wpf data-binding tooltip multibinding datatemplateselector


    【解决方案1】:

    关于您问题的第一部分,您可以像设置文本块一样设置ContentControlToolTip,如果ContentControl 为空,则不会显示工具提示。

    对于TemplateSelector,只需定义两个使用Multibinding和转换器的模板(确保使用ElementName绑定属性以避免UnserValue场景),并绑定ContentTemplateSelector ContentControl 到您的DataTemplateSelector 设置为两个定义的DataTemplates,这里是如何做到这一点的完整示例:

    主窗口 xaml:

    <Window ...
     x:Name="Main"
        Title="MainWindow" Height="450" Width="800" DataContext="{Binding RelativeSource={RelativeSource Self}}"  >
    <Window.Resources>
        <local:CountToStringConverter x:Key="CountToStringConverter"/>
        <DataTemplate x:Key="FirstTemplate">
            <Grid>
                <TextBlock>
                    <TextBlock.Text>
                        <MultiBinding Converter="{StaticResource CountToStringConverter}">
                            <Binding Path="DataContext.Property1" ElementName="Main"/>
                            <Binding Path="DataContext.Property2" ElementName="Main"/>
                        </MultiBinding>
                    </TextBlock.Text>
                </TextBlock>
            </Grid>
        </DataTemplate>
    
        <DataTemplate x:Key="SecondTemplate">
            <Grid>
                <TextBlock>
                    <TextBlock.Text>
                        <MultiBinding Converter="{StaticResource CountToStringConverter}">
                            <Binding Path="DataContext.Property2" ElementName="Main"/>
                            <Binding Path="DataContext.Property1" ElementName="Main"/>
                        </MultiBinding>
                    </TextBlock.Text>
                </TextBlock>
            </Grid>
        </DataTemplate>
        <local:MyTemplateSelector x:Key="MyTemplateSelector" FirstDataTemplate="{StaticResource FirstTemplate}" SecondDataTemplate="{StaticResource SecondTemplate}"/>
    </Window.Resources>
    <Grid>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <ContentControl ContentTemplateSelector="{StaticResource MyTemplateSelector}">
                <ContentControl.ToolTip>
                    <MultiBinding Converter="{StaticResource CountToStringConverter}">
                        <Binding Path="Property1"/>
                        <Binding Path="Property2" />
                    </MultiBinding>
                </ContentControl.ToolTip>
            </ContentControl>
            <TextBlock Grid.Row="1">
    
                <TextBlock.Text>
                    <MultiBinding Converter="{StaticResource CountToStringConverter}">
                        <Binding Path="Property1"/>
                        <Binding Path="Property2" />
                    </MultiBinding>
                </TextBlock.Text>
            </TextBlock>
        </Grid>
      </Grid>
     </Window>
    

    模板选择器、转换器和代码隐藏:

    public class MyTemplateSelector : DataTemplateSelector
    {
        public DataTemplate FirstDataTemplate { get; set; }
        public DataTemplate SecondDataTemplate { get; set; }
        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            // select your template based on item
            return (new Random()).Next(2)==0?SecondDataTemplate:FirstDataTemplate;
        }
    }
    public class CountToStringConverter:IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            if (values == null)
                return null;            
            return values[0]?.ToString() + values[1]?.ToString();
        }
    
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        private string _property1;
        public string Property1
        {
            get { return _property1; }
            set
            {
                if (value == _property1) return;
                _property1 = value;
                OnPropertyChanged();
            }
        }
        private string _property2;
        public string Property2
        {
            get { return _property2; }
            set
            {
                if (value == _property2) return;
                _property2 = value;
                OnPropertyChanged();
            }
        }
    
        public MainWindow()
        {   
            InitializeComponent();
            Property1 = "Property 1";
            Property2 = "Property 2";
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    
    }
    

    更新

    正如我所说,使用 DataTriggers 应该更容易做到这一点,因此为每个图标定义一个 DataTrigger,并根据 property1property2 的值使用相同的值设置 ContentTemplate多值转换器:

    假设您有两个这样定义的 DataTemplate:

    <Window.Resources>
        <DataTemplate x:Key="WarningIconImageTemplate">
            <StackPanel>
                <TextBlock Text="Some Text"></TextBlock>
                <Image Source="/Icons/warningIcon.png"></Image>
            </StackPanel>
        </DataTemplate>
        <DataTemplate x:Key="CautionIconImageTemplate">
            <StackPanel>
                <TextBlock Text="Some Other Text"></TextBlock>
                <Image Source="/Icons/cautionIcon.png"></Image>
            </StackPanel>
        </DataTemplate>
        <local:CountToStringConverter x:Key="CountToStringConverter"/>
    </Window.Resources>
    

    您的 DataTrigger 应该如下所示:

    <ContentControl>
                <ContentControl.Style>
                    <Style TargetType="ContentControl">
                        <Style.Triggers>
                            <DataTrigger >
                                <DataTrigger.Binding>
                                    <MultiBinding Converter="{StaticResource CountToStringConverter}">
                                        <Binding Path="Property1"/>
                                        <Binding Path="Property2" />
                                    </MultiBinding>
                                </DataTrigger.Binding>
                                <DataTrigger.Value>
                                    <system:String>Property 1Property 2</system:String>
                                    <!--update based on your need-->
                                </DataTrigger.Value>
                                <Setter Property="ContentTemplate" Value="{StaticResource WarningIconImageTemplate}"/>
                                <Setter Property="ToolTip" Value="First ToolTip"/>
                            </DataTrigger>
                            <DataTrigger >
                                <DataTrigger.Binding>
                                    <MultiBinding Converter="{StaticResource CountToStringConverter}">
                                        <Binding Path="Property1"/>
                                        <Binding Path="Property2" />
                                    </MultiBinding>
                                </DataTrigger.Binding>
                                <DataTrigger.Value>
                                    <system:String>Property 2Property 1</system:String>
                                    <!--update based on your need-->
                                </DataTrigger.Value>
                                <Setter Property="ContentTemplate" Value="{StaticResource CautionIconImageTemplate}"/>
                                <Setter Property="ToolTip" Value="Second ToolTip"/>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </ContentControl.Style>
            </ContentControl>
    

    现在,如果您想绑定图标,您可以随时使用 ElementName 绑定:

    <Window.Resources>
        <DataTemplate x:Key="WarningIconImageTemplate">
            <StackPanel>
                <TextBlock Text="Some Text"></TextBlock>
                <Image Source="{Binding DataContext.WarningImageSource,ElementName=Main}" ></Image>
            </StackPanel>
        </DataTemplate>
    </Window.Resources>
    

    您还可以考虑的另一个选项是在IconImageTemplate 中定义DataTrigger

    【讨论】:

    • 感谢您的意见。我试图继续你的实施。实际上,我想根据这两个绑定更改的控件是一个 icon (代表警告、错误、成功的图像)。我的 Tempate 选择器返回如下内容:return (DataTemplate)App.Current.TryFindResource("WarningIconImage")。据我了解,我需要将图像的源绑定到返回的 DataTemplate ,但我无法实现这一点。有什么线索吗?
    • 所以基本上,当这两个属性发生变化时,本题原始代码块中标记为Line A、Line B和Line C的行发生了变化。 A 行代表一个图标(图像),B 行是图标的工具提示,C 行是文本。 B线和C线现在已经处理好了。 A线是我苦苦挣扎的地方。
    • 在我看来这更像是一个 DataTrigger,你为什么要首先使用 TemplateSelector !?假设 TemplateSelector 是您的正确选择,那么不同图标的 DataTemplate 之间究竟会发生什么变化,只有图像源?
    • 是的,以及与之相关的工具提示。你也可以参考你上面的评论。由于这两个属性的变化,这是我试图实现的三件事。
    • 非常感谢您的帮助。但是,我无法遵循您定义&lt;DataTrigger.Value&gt; 的部分。我的理解是我必须在这里定义两个属性(我绑定到的)的值,当这两个属性与这些值匹配时,触发数据触发器。但是,这些不是我可以检查的静态值。我将在下一条评论中尝试以更好的方式进行解释。
    【解决方案2】:

    您可以通过以下两种方式之一编写任何属性:

    要么:

    <ContentControl ToolTip="Some Tooltip" />
    

    <ContentControl>
        <ContentControl.ToolTip>
            <MultiBinding Converter="{StaticResource CountToStringConverter}">
                <Binding Path="Property1"/>
                <Binding Path="Property2" />
            </MultiBinding>
        </ContentControl.ToolTip>
    </ContentControl>
    

    【讨论】:

      猜你喜欢
      • 2016-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多