【问题标题】:Setting textblock margin based on content size根据内容大小设置文本块边距
【发布时间】:2019-07-12 05:10:57
【问题描述】:

我正在尝试以以下格式显示当前播放歌曲的整体进度。

hh:mm:ss / hh:mm:ss ---> 当前时间 hh:mm:ss / 总时间 hh:mm:ss

<Border Margin="30,0,20,0" Name="NowPlayingScurbberPanel" RelativePanel.AlignLeftWithPanel="True" RelativePanel.AlignRightWithPanel="True" RelativePanel.Below="NowPlayingButtonPanel" RelativePanel.AlignBottomWithPanel="True">
                                    <StackPanel Visibility="{Binding Path=ShouldProgressBarBeVisible, Converter={StaticResource BoolToVisibilityConverter}}" MinHeight="40">
                                        <Grid>
                                            <Grid.RowDefinitions>
                                                <RowDefinition Height="Auto" />
                                                <RowDefinition Height="*" />
                                            </Grid.RowDefinitions>
                                            <TextBlock x:Uid="NowPlayingCurrentMediaTimeText" Margin="0,0,80,30" Style="{StaticResource NowPlayingMediaTimeStyle}" Grid.Row="0" Text="{Binding Path=DisplayedMediaTimeCurrent}" HorizontalAlignment="Right" />
                                            <TextBlock x:Uid="slash" Margin="0,0,60,30" Style="{StaticResource NowPlayingMediaTimeStyle}" Grid.Row="0" Text=" / " HorizontalAlignment="Right"  />
                                            <Slider x:Uid="NowPlayingScrubber" Margin="0,20,0,0" Style="{StaticResource NowPlayingMediaScrubberStyle}" Grid.Column="1" x:Name="NowPlayingScrubber" Value="{Binding Path=ProgressBarPercentage, Mode=TwoWay}" DragStarting="OnScrubberDragStarted" DropCompleted="OnScrubberDragCompleted" ValueChanged="OnScrubberDragDelta" IsEnabled="{Binding Path=ScrubberEnabled}"  />
                                            <TextBlock x:Uid="NowPlayingTotalMediaTimeText" Margin="60,0,0,30" Style="{StaticResource NowPlayingMediaTimeStyle}" Grid.Row="0" Text="{Binding Path=DisplayedMediaTimeTotal}" HorizontalAlignment="Right"  />
                                        </Grid>
                                    </StackPanel>
                                </Border>

如果总播放时间和当前播放时间不到一小时,但超过一小时而不是“斜线”与总时间重叠,则一切正常。如果我提供额外的保证金,那么时间少于一小时的内容看起来很糟糕。

我如何根据内容长度给出边距,或者有没有更好的解决方案来解决这个问题。

谢谢

【问题讨论】:

    标签: c# wpf xaml uwp uwp-xaml


    【解决方案1】:

    您只需稍微调整布局即可。取决于您希望它看起来如何,您希望它覆盖还是位于滑块的一侧?

    这样的东西会把计时器放在第一位,然后是进度条,但你应该能够根据自己的意愿进行调整。

    <Border Margin="30,0,20,0" Name="NowPlayingScurbberPanel" RelativePanel.AlignLeftWithPanel="True" RelativePanel.AlignRightWithPanel="True" RelativePanel.Below="NowPlayingButtonPanel" RelativePanel.AlignBottomWithPanel="True">
        <StackPanel Visibility="{Binding Path=ShouldProgressBarBeVisible, Converter={StaticResource BoolToVisibilityConverter}}" MinHeight="40">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <TextBlock x:Uid="NowPlayingCurrentMediaTimeText" Margin="5" Style="{StaticResource NowPlayingMediaTimeStyle}" Grid.Row="0" Text="{Binding Path=DisplayedMediaTimeCurrent}" HorizontalAlignment="Right" Grid.Column="0" />
                <TextBlock x:Uid="slash" Margin="5" Style="{StaticResource NowPlayingMediaTimeStyle}" Grid.Row="0" Text=" / " HorizontalAlignment="Right" Grid.Column="1" />
                <TextBlock x:Uid="NowPlayingTotalMediaTimeText" Margin="5" Style="{StaticResource NowPlayingMediaTimeStyle}" Grid.Row="0" Text="{Binding Path=DisplayedMediaTimeTotal}" HorizontalAlignment="Right" Grid.Column="2" />
                <Slider x:Uid="NowPlayingScrubber" Margin="5" Style="{StaticResource NowPlayingMediaScrubberStyle}" x:Name="NowPlayingScrubber" Value="{Binding Path=ProgressBarPercentage, Mode=TwoWay}" DragStarting="OnScrubberDragStarted" DropCompleted="OnScrubberDragCompleted" ValueChanged="OnScrubberDragDelta" IsEnabled="{Binding Path=ScrubberEnabled}" Grid.Column="3" />
            </Grid>
        </StackPanel>
    </Border>
    

    这可以通过使用单个 TextBlockRun E.G. 来进一步简化

    <TextBlock x:Uid="NowPlayingCurrentMediaTimeText" Margin="5" Style="{StaticResource NowPlayingMediaTimeStyle}" Grid.Row="0" HorizontalAlignment="Right" Grid.Column="0" > 
                <Run Text="{Binding Path=DisplayedMediaTimeCurrent}"/> 
                <Run Text=" \ "/> 
                <Run Text="{Binding Path=DisplayedMediaTimeTotal}"/>
     </TextBlock>
    

    【讨论】:

      【解决方案2】:

      你可能需要一个值转换器来获得你想要的边距。

      <StackPanel Orientation="Horizontal">
          <TextBox x:Name="aTextBox" Width="100" Height="30" />
          <TextBlock x:Name="aTextBlock" Width="100" Height="30" Text="some text" 
                     Margin="{Binding ElementName=aTextBox, Path=Text.Length, UpdateSourceTrigger=PropertyChanged}" />
      </StackPanel>
      

      【讨论】:

        【解决方案3】:

        你可以在后面的代码中做到这一点。

        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
        
            private void aTextBox_TextChanged(object sender, TextChangedEventArgs e)
            {
                aTextBlock.Margin = new Thickness(10 + aTextBox.Text.Length * 2, 0, 0, 0);
                aTextBlock.Text = aTextBox.Text;
                aTextBox.Width = 100 + aTextBox.Text.Length * 2;
                aTextBlock.Width = 100 + aTextBox.Text.Length * 2;
            }
        }
        

        <StackPanel Orientation="Horizontal"> <TextBox x:Name="aTextBox" Width="100" Height="30" TextChanged="aTextBox_TextChanged" /> <TextBlock x:Name="aTextBlock" Width="100" Height="30" Text="some text" /> </StackPanel>

        【讨论】:

        • 我要保留其他边距值,只需要设置一次
        • 你不应该在后面的代码中这样做——这可能是你可能做的最糟糕的方式。在后面的代码中添加 UI 样式没有一个单一的理由,这是非常糟糕的做法,并且会导致维护头痛
        • 永远不要说永远。有些事情不能在 xaml 中完成。例如,如果用户需要在运行时动态创建 n 个 UI 元素怎么办。不能在 xaml 中做到这一点。是的,也许您可​​以创建一千个 UI 元素并在运行时取消隐藏它们,但这听起来像是维护夜视镜。
        • @GabrielWorley - 在那种情况下,肯定会有一些 ViewModel 集合或指示这些对象的某些信息的东西,并且您的绑定可以让 XAML 生成它们。您可能希望执行某些 UI 操作,但这些操作也不应该在代码后面完成,只需为它们创建一个行为,然后您的代码也变得专注和可重用。但我个人不认为造型应该坐在那里。
        • @MartinGrundy - 在那种情况下,MVVM 模式开始崩溃。现在,您的 ViewModel 中有一个集合,其中包含有关视图的信息。 MVVM 模式是为了支持支付较少的图形设计师,而不是代码可重用性。令我惊讶的是,程序员为了避免代码落后而遇到的麻烦,是为了什么?他们的团队中有平面设计师吗?如果程序不必支持知道可以开发什么样的模式的图形设计师。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-03
        • 1970-01-01
        • 1970-01-01
        • 2014-02-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多