【问题标题】:How to set proper layout for a set of Images in C# WPF?如何在 C# WPF 中为一组图像设置正确的布局?
【发布时间】:2019-10-30 16:53:39
【问题描述】:

我遇到了哪些问题

我正在尝试为 WPF 构造函数中的一组 Image 对象进行适当的布局。

我现在有什么问题:
1) 我无法正确对齐图像元素。正如您从图像中看到的那样,所有东西都放错了地方。我想我可以在一段时间后将所有东西放在我需要的地方,但是问题2出现了。
2)如果我要尝试调整窗口大小(应用程序将全屏工作,但我需要它以任何分辨率工作)元素将不会调整大小。由于高度和宽度是在 XAML 中定义的,因此我找不到是否可以在不专门为其编写代码的情况下调整它们的大小。

我想做什么

如果我使用完全错误的方法,让我解释一下我想要实现的目标。

在程序中,我应该展示一个人和他的器官。图像可能会有所不同,但相同类型的图像具有相同的宽度和高度。为了显示,我使用了一组 Image 对象。 ImageSource 属性是根据我需要显示的内容以编程方式设置的。这是图像以更清晰地理解。
https://i.stack.imgur.com/l2VX9.png

XAML 的样子

这是我在上图中使用的。

<!-- View Patient -->
        <TabItem x:Name="tabPatientView" Header="Patient View" >
            <Grid Background="#FFE5E5E5">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="auto"/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <Button x:Name="btnViewPatientBack" Content="Назад" Grid.Column="0" Click="BtnNavMenuPatients_Click"/>
                <Image x:Name="imgPatientViewHead" Grid.Column="1" HorizontalAlignment="Left" Margin="682,45,0,0" VerticalAlignment="Top" Width="100" Source="Resources/Bodies/Human/Male/Head.png"/>
                <Image x:Name="imgPatientViewBody" Grid.Column="1" HorizontalAlignment="Left" Height="234" Margin="639,132,0,0" VerticalAlignment="Top" Width="158" Source="Resources/Bodies/Human/Male/Body.png"/>
                <Image x:Name="imgPatientViewArmRight" Grid.Column="1" HorizontalAlignment="Left" Height="86" Margin="402,105,0,0" VerticalAlignment="Top" Width="252" Source="Resources/Bodies/Human/Male/RightArm.png"/>
                <Image x:Name="imgPatientViewArmLeft" Grid.Column="1" HorizontalAlignment="Left" Height="86" Margin="812,105,0,0" VerticalAlignment="Top" Width="252" Source="Resources/Bodies/Human/Male/LeftArm.png"/>
                <Image x:Name="imgPatientViewLegRight" Grid.Column="1" HorizontalAlignment="Left" Height="216" Margin="645,339,0,0" VerticalAlignment="Top" Width="85" Source="Resources/Bodies/Human/Male/RightLeg.png"/>
                <Image x:Name="imgPatientViewLegLeft" Grid.Column="1" HorizontalAlignment="Left" Height="216" Margin="730,339,0,0" VerticalAlignment="Top" Width="92" Source="Resources/Bodies/Human/Male/LeftLeg.png"/>
                <Image x:Name="imgPatientViewBrain" Grid.Column="1" HorizontalAlignment="Left" Height="40" Margin="694,45,0,0" VerticalAlignment="Top" Width="78" Source="Resources/Bodies/Human/Male/Brain.png"/>
                <Image x:Name="imgPatientViewHeart" Grid.Column="1" HorizontalAlignment="Left" Height="59" Margin="740,132,0,0" VerticalAlignment="Top" Width="67" Source="Resources/Bodies/Human/Male/Heart.png"/>
                <Image x:Name="imgPatientViewBreath" Grid.Column="1" HorizontalAlignment="Left" Height="99" Margin="671,120,0,0" VerticalAlignment="Top" Width="126" Source="Resources/Bodies/Human/Male/Breath.png"/>
                <Image x:Name="imgPatientViewLiver" Grid.Column="1" HorizontalAlignment="Left" Height="39" Margin="659,224,0,0" VerticalAlignment="Top" Width="71" Source="Resources/Bodies/Human/Male/Liver.png"/>
                <Image x:Name="imgPatientViewKidneys" HorizontalAlignment="Left" Height="55" VerticalAlignment="Top" Width="148" Margin="659,279,0,0" Grid.Column="1" Source="Resources/Bodies/Human/Male/Kidneys.png"/>
                <Image x:Name="imgPatientViewStomach" Grid.Column="1" HorizontalAlignment="Left" Height="41" Margin="701,233,0,0" VerticalAlignment="Top" Width="71" Source="Resources/Bodies/Human/Male/Stomach.png"/>
                <Image x:Name="imgPatientViewIntestines" Grid.Column="1" HorizontalAlignment="Left" Height="57" Margin="682,263,0,0" VerticalAlignment="Top" Width="68" Source="Resources/Bodies/Human/Male/Intestines.png"/>
                <Image x:Name="imgPatientViewBladder" Grid.Column="1" HorizontalAlignment="Left" Height="33" Margin="716,292,0,0" VerticalAlignment="Top" Width="37" Source="Resources/Bodies/Human/Male/Bladder.png"/>
                <Image x:Name="imgPatientViewReproduction" HorizontalAlignment="Left" Height="33" VerticalAlignment="Top" Width="37" Margin="716,325,0,0" Grid.Column="1" Source="Resources/Bodies/Human/Male/Reproduction.png"/>
                <Image x:Name="imgPatientViewSpleen" Grid.Column="1" HorizontalAlignment="Left" Height="26" Margin="781,205,0,0" VerticalAlignment="Top" Width="25" Source="Resources/Bodies/Human/Male/Spleen.png"/>
            </Grid>
        </TabItem>

有什么方法可以让这件事变得更容易吗?我真的认为我在那里做了很多不必要的工作。对于这种情况,也许有一些控制元素。不能说我对WPF很熟悉。

【问题讨论】:

  • 使用Canvas 和绝对定位可能会更好。你没有解释的是你如何以及为什么把事情放在你做的地方。
  • @DonBoitnott 好的,将尝试使用 Canvas。不知道你所说的如何以及为什么这样放置是什么意思。我正在尝试放置器官图像,使其与健康的类人动物相匹配,但无法理解如何使图像大小相对于……任何东西,因为它们在 XAML 中设置为纯数字。
  • 我的意思是您是否允许根据用户选择来来去去。此外,由于缩放似乎是一个问题,例如,您将如何决定心脏的去向?不是相对的,我的意思是具体的。随着基础图像的缩放,每个部分的坐标都会随着它们的比例发生变化。除非我阅读的内容比您的意思要多,否则有很多复杂的定位需要解决。
  • 如果这些都是同样大小的图片,而且没有器官的地方都是透明的,那岂不是简单多了?你可以把它们覆盖起来。身体和四肢是分开的图片,这似乎很奇怪。
  • @Andy 该程序是医学模拟器。用户将能够弹出器官并用一些增强物替换它们。例如。砍掉某人的腿并安装假肢将是一种正常的做法,或者制作一个铁心因为为什么不。因此,所有内容都必须是单独的图片。

标签: c# wpf


【解决方案1】:

我会肯定使用 ListView。每个图像都将位于 ListView 项中。 Listview ItemsPanel(ListView 用来存储其元素的容器)将是一个画布。然后每个列表视图项都将包含一个用于描述其位置的画布的附加属性。

每个图像都是类 (ViewModel) 的一个实例,它实现了您可以绑定到的属性。这些属性将是您描述相对于彼此或画布的图像位置的方式。

就您与相对尺寸和分辨率有关的其他问题而言。解决方案真的很简单!

-一旦你完成了你的 ListView,或者把它包装在一个 UserControl 中,或者其他什么,只需将它包装在一个 ViewBox 中。 XAML 将负责为您调整所有子元素的大小。

-在相对大小和位置方面,请确保您的 XAML 图像元素的 Stretch 设置为“统一”(以便始终保留每个图像的纵横比)。然后在代码中,对于每个身体部位,您只需将其中一个尺寸(宽度或高度)设置为与画布相比的相对大小,假设身体图片是最大的图像并且是决定画布大小的图像。

这是一个如何创建 ListView 的示例:

<ListView 
Name="BodyListView"
ItemsSource="{Binding BodyParts}"
SelectionMode="Single"
ItemContainerStyle="{DynamicResource SelectBodyPartListViewItem}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Disabled">

     <ListView.ItemsPanel>
          <ItemsPanelTemplate>
               <Canvas/>
          </ItemsPanelTemplate>
     </ListView.ItemsPanel>

     <ListView.ItemTemplate>
          <DataTemplate>
               <Grid >
               <Image Source="{Binding Image}" Canvas.Top="{Binding CanvasTop}" 
                    Canvas.Right="{Binding CanvasRight}" Height="{Binding ImgHeight}" Stretch="Uniform"/>

                </Grid>
          </DataTemplate>
      </ListView.ItemTemplate>
</ListView>

【讨论】:

    【解决方案2】:

    您应该使用 Canvas 控件。它允许您为每个图像输入特定的坐标。

    如果您需要调整图像大小,您可以设置明确的宽度或高度,它会为您调整大小(请参阅https://docs.microsoft.com/en-us/dotnet/framework/wpf/controls/how-to-use-the-image-element)。

    您还可以选择使用渲染转换https://docs.microsoft.com/en-us/dotnet/framework/wpf/graphics-multimedia/transforms-overview

    然后,如果您需要整个 Canvas 进行缩放(例如,对于调整大小的窗口或父控件),那么您可以将整个内容放在 ViewBox 控件中。

    图像的一个问题是,当它们在 ViewBox(或任何其他东西)中放大时会变得模糊。如果您有矢量格式的原始图像,您可以使用 Inkscape 或类似程序将它们转换为 Xaml。这将防止像素化,甚至可能降低图像尺寸。不过,这对您来说可能无关紧要。

    【讨论】:

      【解决方案3】:

      或者,如果您不想采用我在另一个答案中提到的 ViewModel + ListView 方法。你可以这样做:

      <TabItem x:Name="tabPatientView" Header="Patient View">
          <ViewBox>
              <Canvas Height="100" Width="100">
                  <Image x:Name="imgPatientViewHead" Canvas.Top="Y" Canvas.Right="X" Height="26" Stretch="Uniform" Source="Resources/Bodies/Human/Male/Head.png"/>
                  ...
                  <Image x:Name="imgPatientViewSpleen" Canvas.Top="Y" Canvas.Right="X"  Height="26" Stretch="Uniform" Source="Resources/Bodies/Human/Male/Spleen.png"/>
              </Canvas>
          </ViewBox>
      </TabItem>
      

      注意:如果您明确设置画布的高度,那么您将使每个图像高度相对于该设置高度。显然 Canvas.Top 和 Canvas.Right 的值需要是数字而不是 X 和 Y...

      【讨论】:

      • 太棒了,效果最好,谢谢!唯一要提到的 - 我必须为画布设置高度和宽度,否则它只会折叠为 0 并且看不到任何图片。
      • 太棒了!是啊,你说得对。我更新了我的代码,以免让其他人失望。
      【解决方案4】:

      将所有 Image 元素包装在 Canvas 元素中,然后包装在 ViewBox 元素中可能会对您有所帮助。

      当父窗口调整大小时,Grid 元素中包含的视图框将调整大小,并且内部图像将调整为视图框比例。

      例如:

       <Viewbox x:Name="mViewBox"  Stretch="Uniform" >
          <Canvas Width="500" Height="500">
                      <Image x:Name="imgPatientViewHead" Grid.Column="1" HorizontalAlignment="Left" Margin="682,45,0,0" VerticalAlignment="Top" Width="100" Source="Resources/Bodies/Human/Male/Head.png"/>
                      <Image x:Name="imgPatientViewBody" Grid.Column="1" HorizontalAlignment="Left" Height="234" Margin="639,132,0,0" VerticalAlignment="Top" Width="158" Source="Resources/Bodies/Human/Male/Body.png"/>
                      <Image x:Name="imgPatientViewArmRight" Grid.Column="1" HorizontalAlignment="Left" Height="86" Margin="402,105,0,0" VerticalAlignment="Top" Width="252" Source="Resources/Bodies/Human/Male/RightArm.png"/>
                      <Image x:Name="imgPatientViewArmLeft" Grid.Column="1" HorizontalAlignment="Left" Height="86" Margin="812,105,0,0" VerticalAlignment="Top" Width="252" Source="Resources/Bodies/Human/Male/LeftArm.png"/>
                      <Image x:Name="imgPatientViewLegRight" Grid.Column="1" HorizontalAlignment="Left" Height="216" Margin="645,339,0,0" VerticalAlignment="Top" Width="85" Source="Resources/Bodies/Human/Male/RightLeg.png"/>
                      <Image x:Name="imgPatientViewLegLeft" Grid.Column="1" HorizontalAlignment="Left" Height="216" Margin="730,339,0,0" VerticalAlignment="Top" Width="92" Source="Resources/Bodies/Human/Male/LeftLeg.png"/>
                      <Image x:Name="imgPatientViewBrain" Grid.Column="1" HorizontalAlignment="Left" Height="40" Margin="694,45,0,0" VerticalAlignment="Top" Width="78" Source="Resources/Bodies/Human/Male/Brain.png"/>
                      <Image x:Name="imgPatientViewHeart" Grid.Column="1" HorizontalAlignment="Left" Height="59" Margin="740,132,0,0" VerticalAlignment="Top" Width="67" Source="Resources/Bodies/Human/Male/Heart.png"/>
                      <Image x:Name="imgPatientViewBreath" Grid.Column="1" HorizontalAlignment="Left" Height="99" Margin="671,120,0,0" VerticalAlignment="Top" Width="126" Source="Resources/Bodies/Human/Male/Breath.png"/>
                      <Image x:Name="imgPatientViewLiver" Grid.Column="1" HorizontalAlignment="Left" Height="39" Margin="659,224,0,0" VerticalAlignment="Top" Width="71" Source="Resources/Bodies/Human/Male/Liver.png"/>
                      <Image x:Name="imgPatientViewKidneys" HorizontalAlignment="Left" Height="55" VerticalAlignment="Top" Width="148" Margin="659,279,0,0" Grid.Column="1" Source="Resources/Bodies/Human/Male/Kidneys.png"/>
                      <Image x:Name="imgPatientViewStomach" Grid.Column="1" HorizontalAlignment="Left" Height="41" Margin="701,233,0,0" VerticalAlignment="Top" Width="71" Source="Resources/Bodies/Human/Male/Stomach.png"/>
                      <Image x:Name="imgPatientViewIntestines" Grid.Column="1" HorizontalAlignment="Left" Height="57" Margin="682,263,0,0" VerticalAlignment="Top" Width="68" Source="Resources/Bodies/Human/Male/Intestines.png"/>
                      <Image x:Name="imgPatientViewBladder" Grid.Column="1" HorizontalAlignment="Left" Height="33" Margin="716,292,0,0" VerticalAlignment="Top" Width="37" Source="Resources/Bodies/Human/Male/Bladder.png"/>
                      <Image x:Name="imgPatientViewReproduction" HorizontalAlignment="Left" Height="33" VerticalAlignment="Top" Width="37" Margin="716,325,0,0" Grid.Column="1" Source="Resources/Bodies/Human/Male/Reproduction.png"/>
                      <Image x:Name="imgPatientViewSpleen" Grid.Column="1" HorizontalAlignment="Left" Height="26" Margin="781,205,0,0" VerticalAlignment="Top" Width="25" Source="Resources/Bodies/Human/Male/Spleen.png"/>
          </Canvas>
      </Viewbox>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-22
        • 1970-01-01
        • 1970-01-01
        • 2022-11-15
        • 2017-04-23
        • 1970-01-01
        相关资源
        最近更新 更多