WPF исчезает текст строки состояния через X секунд? - PullRequest
18 голосов
/ 19 октября 2010

Я пытаюсь придумать ненавязчивый способ для отображения незначительных сообщений об ошибках для пользователя. Итак, я добавил строку состояния в мою форму,

    <StatusBar Margin="0,288,0,0" Name="statusBar" Height="23" VerticalAlignment="Bottom">
        <TextBlock Name="statusText">Ready.</TextBlock>
    </StatusBar>

И затем, когда они нажимают кнопку «Добавить», он должен что-то делать или отображать сообщение об ошибке:

private void DownloadButton_Click(object sender, RoutedEventArgs e)
{
    addressBar.Focus();
    var url = addressBar.Text.Trim();
    if (string.IsNullOrEmpty(url))
    {
        statusText.Text = "Nothing to add.";
        return;
    }
    if (!url.Contains('.'))
    {
        statusText.Text = "Invalid URL format.";
        return;
    }
    if (!Regex.IsMatch(url, @"^\w://")) url = "http://" + url;
    addressBar.Text = "";

Но сообщение просто хранится в течение всей жизни приложения ... Я думаю, что я должен сбросить его примерно через 5 секунд ... Как я могу установить таймер для этого?

Бонус: Как мне придать этому эффекту плавного затухания?


Я создал System.Timers.Timer,

    private Timer _resetStatusTimer = new Timer(5000);

    void _resetStatusTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        statusText.Text = "Ready";
    }

Но событие Elapsed выполняется в потоке, отличном от пользовательского интерфейса, что ему не нравится ... как это обойти?

Ответы [ 2 ]

37 голосов
/ 19 октября 2010

Вы можете использовать раскадровку, чтобы выполнить трюк.

<Storyboard x:Key="Storyboard1">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="statusBarItem">
            <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
            <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
            <EasingDoubleKeyFrame KeyTime="0:0:3" Value="1"/>
            <EasingDoubleKeyFrame KeyTime="0:0:4" Value="0"/>
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>

Когда необходимо отобразить сообщение, вы просто программно вызываете метод Begin для StoryBoard или вставляете триггер, как показано ниже.

<Window.Triggers>
    <EventTrigger RoutedEvent="TextBoxBase.TextChanged" SourceName="textBox">
        <BeginStoryboard Storyboard="{StaticResource Storyboard1}"/>
    </EventTrigger>
</Window.Triggers>

РЕДАКТИРОВАТЬ: Другой вариант заключается в следующем:

<TextBlock Name="statusText" Text="{Binding Path=StatusBarText, NotifyOnTargetUpdated=True}">
        <TextBlock.Triggers>
            <EventTrigger RoutedEvent="Binding.TargetUpdated">
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity">
                            <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:0.25" Value="1"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:4" Value="1"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:5" Value="0"/>
                        </DoubleAnimationUsingKeyFrames>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </TextBlock.Triggers>

Затем создать в этом случае DependencyProperty с именем StatusBarText, который реализуется какследуйте:

public string StatusBarText
    {
        get { return (string)GetValue(StatusBarTextProperty); }
        set { SetValue(StatusBarTextProperty, value); }
    }

    // Using a DependencyProperty as the backing store for StatusBarText.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty StatusBarTextProperty =
        DependencyProperty.Register("StatusBarText", typeof(string), typeof(MyOwnerClass), new UIPropertyMetadata(""));

Надеюсь, это поможет.

8 голосов
/ 19 октября 2010

Ваш таймер - хороший подход, и вы даже определили свою проблему: вам просто нужен способ доступа к statusText.Text в потоке пользовательского интерфейса.(В WPF потокам, отличным от потока пользовательского интерфейса, запрещен доступ к элементам пользовательского интерфейса).На помощь приходит диспетчер WPF:

http://msdn.microsoft.com/en-us/magazine/cc163328.aspx#S5

Вы можете использовать класс DispatcherTimer, чтобы сделать именно то, что вы пытались (вот их код):

// Create a Timer with a Normal Priority
_timer = new DispatcherTimer();

// Set the Interval to 2 seconds
_timer.Interval = TimeSpan.FromMilliseconds(2000); 

// Set the callback to just show the time ticking away
// NOTE: We are using a control so this has to run on 
// the UI thread
_timer.Tick += new EventHandler(delegate(object s, EventArgs a) 
{ 
    statusText.Text = string.Format(
        "Timer Ticked:  {0}ms", Environment.TickCount); 
});

// Start the timer
_timer.Start();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...