【问题标题】:Building a custom progress bar for Windows phone 8 App Using XAML and C#使用 XAML 和 C# 为 Windows phone 8 应用程序构建自定义进度条
【发布时间】:2014-04-16 12:50:24
【问题描述】:

我正在尝试制作一个随时间减少的条形图。

使用的xaml是

     <Grid x:Name="LayoutRoot" Background="Transparent">
      <TextBlock  Text="Timer :-" FontSize="35" Width="120" Height="70" Margin="138,167,222,531" ></TextBlock>
    <TextBlock x:Name="clock" FontSize="35" Width="100" Height="70" Margin="259,169,121,529" ></TextBlock>

    <Image x:Name="bar" Width="350" Height="20" Source="Assets/progress_bar_bg.png" Margin="65,271,65,477" ></Image>
    <Image x:Name="gbar"  Width="350" Height="20" Source="Assets/green_progress_bar.png" Margin="65,271,65,477" ></Image>

</Grid>

我的 c# 代码是

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Navigation;
    using Microsoft.Phone.Controls;
    using System.Windows.Threading;
    using Microsoft.Phone.Shell;

    namespace PhoneApp1
    {
        public partial class ProgressBar : PhoneApplicationPage
        {
    public ProgressBar()
    {
        InitializeComponent();

        newTimer.Interval = TimeSpan.FromSeconds(1);
        newTimer.Tick += OnTimerTick;
        newTimer.Start();
        clock.Text = " 00:60";
    }

    DispatcherTimer newTimer = new DispatcherTimer();
    int counter = 60;

    int width = 350;
    double i=5.8;

    void OnTimerTick(Object sender, EventArgs args)
    {
        counter--;

        if (counter < 0)
        {
            newTimer.Stop();
            counter = 60;
        }
        else
        {


                gbar.Width = width - i;

                clock.Text = " 00:" + counter.ToString();
                i=i+5.8;

            }
        }
    }
}

我已经减小了宽度,使得图像 green_progress_bar.png 的大小应该减小,但问题是它从两端减小,我希望它应该从右到左减小,因为时间从 60 秒减少到 0秒。而且高度也随着时间的推移而降低,我希望图像高度被固定。

这是我的情况的图像。

我希望栏的宽度应该从右到左减小。但它从两端减小。 请帮帮我。

提前致谢。

【问题讨论】:

  • 还请注意,当您的时间低于 10 秒时,它实际上会显示 00:9 而不是 00:09...
  • 必须使用图片吗?修改一个Slider的样式不是更简单吗?
  • @mehow 我已经纠正了你指出的问题,当时间低于 10 秒时,它实际上显示 00:9 而不是 00:09
  • @Romasz 图片不是强制性的,但我对 Slider 了解不多,所以如果你能帮助我,我会很高兴的。

标签: c# wpf xaml windows-phone-8


【解决方案1】:

好的 - 这将是一个很长的帖子。所以首先 - 结果:

我在您的代码中进行了很多更改(IMO 某些事情可能会有所改进)。首先 - Slider 的样式(我已经删除了大部分不需要的东西。完整的模板可以在 MSDN 或使用 Blend 中找到):

<phone:PhoneApplicationPage.Resources>
    <Style x:Key="SliderStyle1" TargetType="Slider">
        <Setter Property="BorderThickness" Value="0"/>
        <Setter Property="BorderBrush" Value="Transparent"/>
        <Setter Property="Maximum" Value="10"/>
        <Setter Property="Minimum" Value="0"/>
        <Setter Property="Value" Value="0"/>
        <Setter Property="Background" Value="{StaticResource PhoneChromeBrush}"/>
        <Setter Property="Foreground" Value="{StaticResource PhoneAccentBrush}"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Slider">
                    <Grid Background="Transparent">
                        <Grid x:Name="HorizontalTemplate" Margin="{StaticResource PhoneHorizontalMargin}">
                            <Rectangle x:Name="HorizontalTrack" Fill="{TemplateBinding Background}" Height="12" IsHitTestVisible="False" Margin="0,22,0,50"/>
                            <Rectangle x:Name="HorizontalFill" Fill="GreenYellow" Height="12" IsHitTestVisible="False" Margin="0,22,0,50">
                                <Rectangle.Clip>
                                    <RectangleGeometry Rect="0, 0, 6, 12"/>
                                </Rectangle.Clip>
                            </Rectangle>
                            <Ellipse x:Name="HorizontalCenterElement" HorizontalAlignment="Left" Height="12" Margin="0,16,0,44" Width="12" Fill="GreenYellow">
                                <Ellipse.RenderTransform>
                                    <TranslateTransform/>
                                </Ellipse.RenderTransform>
                            </Ellipse>
                        </Grid>                            
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</phone:PhoneApplicationPage.Resources>

上面代码中最重要的是:HorizontalTrackHorizontalFillHorizontalCenterElement——你可以改变颜色、形状等等。我已经将中心元素设置为椭圆,所以它在最后有点圆润。如果你只是玩它,那就最好了。使用样式如下:

<Grid x:Name="LayoutRoot" Background="Transparent">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <Grid.RowDefinitions>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="2*"/>
            <RowDefinition Height="6*"/>
        </Grid.RowDefinitions>
        <Button x:Name="buttonStart" VerticalAlignment="Top" Content="Start" Grid.Row="0"/>
        <TextBlock Name="clock" HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding ClockText}" Grid.Row="1"/>
        <Slider Name="gbar" VerticalAlignment="Center" Orientation="Horizontal" HorizontalAlignment="Stretch" 
                Grid.Row="2" Style="{StaticResource SliderStyle1}" IsHitTestVisible="False"
                Value="{Binding ValueLeft, Mode=TwoWay}" Maximum="{Binding MaxValue}"/>

    </Grid>
</Grid>

几件事:

  • 我已更改 UIElements 的内容并将它们绑定到实现 INotifyPropertyChanged 的​​属性
  • 我已禁用 Slider 以进行点击测试 - 因此用户将无法通过触摸来更改它

后面的其余代码:

public partial class MainPage : PhoneApplicationPage, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void RaiseProperty(string property = null)
    { if (this.PropertyChanged != null)                this.PropertyChanged(this, new PropertyChangedEventArgs(property)); }

    private TimeSpan timeLeft = TimeSpan.FromSeconds(60);
    public TimeSpan TimeLeft
    {
        get { return timeLeft; }
        set
        {
            timeLeft = value;
            RaiseProperty("ClockText");
            RaiseProperty("ValueLeft");
        }
    }

    public string ClockText { get { return timeLeft.ToString("m\\:ss"); } }

    public double ValueLeft { get { return TimeLeft.Ticks; } }

    private double maxValue = TimeSpan.FromSeconds(60).Ticks;
    public double MaxValue // number of seconds
    {
        get { return maxValue; }
        set
        {
            TimeLeft = TimeSpan.FromSeconds(value);
            maxValue = TimeLeft.Ticks;
            RaiseProperty("MaxValue");
        }
    }

    System.Threading.Timer newTimer;
    private bool timerStarted = false;

    public MainPage()
    {
        InitializeComponent();
        this.DataContext = this;
        newTimer = new Timer(OnTimerTick);
        buttonStart.Click += buttonStart_Click;
    }

    private void buttonStart_Click(object sender, RoutedEventArgs e)
    {
        if (!timerStarted)
        {
            buttonStart.Content = "STOP";
            MaxValue = 60;
            timerStarted = true;
            newTimer.Change(TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(1)); // start timer right now and invoke every second
        }
        else
        {
            buttonStart.Content = "Start";
            timerStarted = false;
            newTimer.Change(0, Timeout.Infinite); // stop the timer
        }
    }

    void OnTimerTick(object state)
    { Dispatcher.BeginInvoke(() => TimeLeft -= TimeSpan.FromSeconds(1)); }
}

这里有几件事:

  • 我已经组织了属性,现在当我更改 TimeLeft 时,TextBlock 和 Slider 会更新 - 绑定
  • 我已将您的 DispatcherTimer 更改为 System.Threading.Timer - 它在单独的线程上运行,因此不会阻塞 UI(当有更多计算时)
  • 由于该单独的线程,回调内部的更改(在 UI 上)必须通过 Dispatcher 进行。

当您的间隔为 1 秒时,此示例肯定适用于 DispatcherTimer,但如果您计划执行更多计算,则第二个 Timer 可能是更好的选择。 (这只是一种不同的可能性)。

【讨论】:

  • 非常感谢您的帮助 :) :)
【解决方案2】:

为两张图片设置HorizontalAlignment="Left"。默认居中。

【讨论】:

  • 它没有工作,宽度仍然从两侧减小。
  • green_progress_bar.png 的高度也随着时间的推移而减小
【解决方案3】:

问题在于图片拉伸,可以通过Stretch="None"禁用

<Image x:Name="gbar" Stretch="None" Width="350" Height="20" Source="Assets/green_progress_bar.png" />

也尽量不要使用Margin 进行精确定位,GridStackPanel 应该会有所帮助。

我强烈建议不要制作自己的进度条,而是像我们在 http://highrobotics.com/we-did-it/wpf-themes.aspx 中所做的那样为 Microsoft ProgressBar 控件着色/设计

【讨论】:

  • Strech="None" 解决了高度降低的问题。但宽度仍然从两侧减小。
  • 我知道 microsoft ProgressBar 控件,但我想做一些类似的东西,但感谢@Artru 的回复。
  • 然后为图像设置 Horizo​​ntalAlignment="Left"(正如 Igor Kulman 建议的那样)并删除边距。这会将图像与父面板的左侧对齐。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多