如何在文本块周围设置图像位置

Posted

技术标签:

【中文标题】如何在文本块周围设置图像位置【英文标题】:How to set image placement around a textblock 【发布时间】:2021-10-20 21:31:23 【问题描述】:

我是 C# 和 wpf 的新手,所以如果这是一个愚蠢的问题,请不要批评。

我在 DockPanel 中有 Image 和 TextBlock,然后我有一个 ComboBox,用于控制图像在文本周围的显示位置。 ComboBox 项是(“文本左侧”、“文本右侧”、“文本上方”、“文本下方”、“中心”)

我可以通过绑定 DockPanel.Dock 来进行左、右、上和下操作,但是对于中心,我需要将图像放在文本后面(覆盖它们),而 DockPanel 不允许我这样做。我想使用 Canvas,但出于其他原因(文本换行问题等)特别要求我不要使用。

现在我只需要在从组合框中选择“中心”时覆盖图像和文本。

xaml

<DockPanel>
    <Image Source="Binding Path=ImageSource, UpdateSourceTrigger=PropertyChanged" DockPanel.Dock="Binding Path=ImagePlacementDisplay, UpdateSourceTrigger=PropertyChanged"/>
    <TextBlock TextWrapping="WrapWithOverflow" Text="Binding Path=Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged" /> 

查看模型

    public string SelectedImagePlacement
    
        get  return _ex2.ImagePlacement; 
        set
        
            _ex2.ImagePlacement = value;
            OnPropertyChanged("SelectedImagePlacement");
            OnPropertyChanged("ImagePlacementDisplay");
        
    

    public string ImagePlacementDisplay
    
        get
        
            switch (SelectedImagePlacement)
            
                case "0": 
                    return "Left";
                case "1": 
                    return "Right";
                case "2":
                    return "Top";
                case "3":
                    return "Bottom";
                case "4":
                    return "Center"; //not working
                default:
                    return "Right";
            
        
        set
        
            OnPropertyChanged("ImagePlacementDisplay");
        
    

【问题讨论】:

您忘记显示 xaml。 z 顺序与子面板的顺序相同,先放Image,然后是TextBox,后者将在上方。或者您可以使用ZIndex 进行更改。 @Sinatr 我包含了我的代码的 sn-ps,但我不确定它是否有帮助,或者它只是让我的问题更加混乱。我尝试使用 Panel.ZIndex,但这不仅仅是我想要的。 所以您希望两个控件都为occupy the middle 并重叠?您可以使用自定义枚举制作自己的面板来控制对齐。或者您可以忘记DockPanel,使用Grid 并使用数据触发器安排控件。 【参考方案1】:

您可以使用数据触发器来修改控制位置。

下面是 2x2 Grid,根据 ComboBox.SelectedIndex 的值,数据触发器将安排 Image(用黄色网格模拟)和 TextBlock 的位置。

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Grid Background="Yellow">
        <Grid.Style>
            <Style TargetType="Grid">
                <Style.Triggers>
                    <DataTrigger Binding="Binding SelectedIndex, ElementName=combobox" Value="0">
                        <Setter Property="Grid.Row" Value="0" />
                        <Setter Property="Grid.Column" Value="0" />
                        <Setter Property="Grid.RowSpan" Value="2" />
                        <Setter Property="Grid.ColumnSpan" Value="1" />
                    </DataTrigger>
                    <DataTrigger Binding="Binding SelectedIndex, ElementName=combobox" Value="1">
                        <Setter Property="Grid.Row" Value="0" />
                        <Setter Property="Grid.Column" Value="1" />
                        <Setter Property="Grid.RowSpan" Value="2" />
                        <Setter Property="Grid.ColumnSpan" Value="1" />
                    </DataTrigger>
                    <DataTrigger Binding="Binding SelectedIndex, ElementName=combobox" Value="2">
                        <Setter Property="Grid.Row" Value="0" />
                        <Setter Property="Grid.Column" Value="0" />
                        <Setter Property="Grid.RowSpan" Value="1" />
                        <Setter Property="Grid.ColumnSpan" Value="2" />
                    </DataTrigger>
                    <DataTrigger Binding="Binding SelectedIndex, ElementName=combobox" Value="3">
                        <Setter Property="Grid.Row" Value="1" />
                        <Setter Property="Grid.Column" Value="0" />
                        <Setter Property="Grid.RowSpan" Value="1" />
                        <Setter Property="Grid.ColumnSpan" Value="2" />
                    </DataTrigger>
                    <DataTrigger Binding="Binding SelectedIndex, ElementName=combobox" Value="4">
                        <Setter Property="Grid.Row" Value="0" />
                        <Setter Property="Grid.Column" Value="0" />
                        <Setter Property="Grid.RowSpan" Value="2" />
                        <Setter Property="Grid.ColumnSpan" Value="2" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Grid.Style>
    </Grid>
    <TextBlock Text="Bla bla bla" VerticalAlignment="Center" HorizontalAlignment="Center">
        <TextBlock.Style>
            <Style TargetType="TextBlock">
                <Style.Triggers>
                    <DataTrigger Binding="Binding SelectedIndex, ElementName=combobox" Value="0">
                        <Setter Property="Grid.Row" Value="0" />
                        <Setter Property="Grid.Column" Value="1" />
                        <Setter Property="Grid.RowSpan" Value="2" />
                        <Setter Property="Grid.ColumnSpan" Value="1" />
                    </DataTrigger>
                    <DataTrigger Binding="Binding SelectedIndex, ElementName=combobox" Value="1">
                        <Setter Property="Grid.Row" Value="0" />
                        <Setter Property="Grid.Column" Value="0" />
                        <Setter Property="Grid.RowSpan" Value="2" />
                        <Setter Property="Grid.ColumnSpan" Value="1" />
                    </DataTrigger>
                    <DataTrigger Binding="Binding SelectedIndex, ElementName=combobox" Value="2">
                        <Setter Property="Grid.Row" Value="1" />
                        <Setter Property="Grid.Column" Value="0" />
                        <Setter Property="Grid.RowSpan" Value="1" />
                        <Setter Property="Grid.ColumnSpan" Value="2" />
                    </DataTrigger>
                    <DataTrigger Binding="Binding SelectedIndex, ElementName=combobox" Value="3">
                        <Setter Property="Grid.Row" Value="0" />
                        <Setter Property="Grid.Column" Value="0" />
                        <Setter Property="Grid.RowSpan" Value="1" />
                        <Setter Property="Grid.ColumnSpan" Value="2" />
                    </DataTrigger>
                    <DataTrigger Binding="Binding SelectedIndex, ElementName=combobox" Value="4">
                        <Setter Property="Grid.Row" Value="0" />
                        <Setter Property="Grid.Column" Value="0" />
                        <Setter Property="Grid.RowSpan" Value="2" />
                        <Setter Property="Grid.ColumnSpan" Value="2" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </TextBlock.Style>
    </TextBlock>
    <ComboBox x:Name="combobox" VerticalAlignment="Bottom" Grid.Row="1" SelectedIndex="0">
        <ComboBoxItem Content="Left"/>
        <ComboBoxItem Content="Right"/>
        <ComboBoxItem Content="Up"/>
        <ComboBoxItem Content="Down"/>
        <ComboBoxItem Content="Center"/>
    </ComboBox>
</Grid>

演示:

它可能不是最好看的解决方案,但它展示了数据触发器的强大功能,并且可能会教你一些布局(wpf 中非常重要的技能)。

更好的方法是使用枚举类型的自定义依赖属性创建自定义Panel 来控制子排列。

【讨论】:

感谢您提供替代方案。但是这种方法是硬连线到 UI 的,如果我进行一些更改,将很难维护。我仍然需要在它们之间添加边距(一个数字框控制它),文本的框架等。所以我猜我需要尝试像你说的那样制作一个自定义面板。

以上是关于如何在文本块周围设置图像位置的主要内容,如果未能解决你的问题,请参考以下文章

如何在网格中移动图像的相对位置?

如何使用彩色文本框在图像周围环绕文本?

如何在可移动图像周围环绕文本?

如何在本机反应中在图像周围浮动文本

真的没有办法在 flexbox 中的图像周围环绕文本吗?

如何在图像周围包装一些文字?