Ответы пользователя по тегу WPF
  • Как менять цвет при наведении на контрол?

    gdt
    @gdt
    Программист
    Вот так работает:
    <ControlTemplate x:Key="TestButtonTemplate" TargetType="Button">
        <Border Background="{TemplateBinding Background}"
                BorderThickness="0"
                CornerRadius="5"
                Height="{TemplateBinding Height}"
                Width="{TemplateBinding Width}">
            <ContentControl Foreground="{TemplateBinding Foreground}"
                            Content="{TemplateBinding Content}"
                            VerticalAlignment="Center"
                            HorizontalAlignment="Center"
                            FontSize="{TemplateBinding FontSize}"
                            FontFamily="{TemplateBinding FontFamily}"/>
        </Border>
    
        <ControlTemplate.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="Background" Value="Red" />
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>


    Лениво разбираться в причинах, но наверное вам нужно менять свойства самого контрола, раз вы на них биндитесь в Border
    Ответ написан
    Комментировать
  • Как мгновенно завершить Task?

    gdt
    @gdt
    Программист
    Извините, что не отвечаю на ваш вопрос - а почему не используете https://github.com/XamlAnimatedGif/XamlAnimatedGif ?

    По делу - если мне не изменяет память, нет простого способа прибить Task, для этого нужно использовать CancellationTokenSource, что вы и делаете в приведенном примере. Если отмена через CancellationTokenSource не срабатывает по какой-то причине - поставьте брейкпоинты или навтыкайте логов через каждую строку, найдите проблемное место, и уже исходя из этой информации решайте.
    Исходя из вашей проблемы, для начала после отмены можно просто подождать завершения таска:
    // Метод в котором останавливаете анимацию
    cancellationTokenSource3.Cancel();
    await th_Image3;

    или
    // Метод в котором останавливаете анимацию
    cancellationTokenSource3.Cancel();
    th_Image3.GetAwaiter().GetResult();

    Так вы по-крайней мере должны избавиться от наложения тасков друг на друга.

    Далее, таски можно чуть-чуть проще запускать, вот так:
    th_Image3 = Task.Run(() => 
    { 
        // ......
    });


    Кроме того, если вам действительно нужно, чтобы код внутри Task.Run всегда выполнялся только в единственном экземпляре - это значит, что вам нужна критическая секция. В данном случае можно сделать при помощи семафоров:
    // ......................
    Semaphore _semaphore = new Semaphore(1, 1);
    // ......................
    th_Image3 = Task.Run(() =>
    {
        _semaphore.WaitOne();
    
        try
        {
            // Показ GIF
        }
        finally
        {
            _semaphore.Release();
        }
    });


    Или же можно использовать метод ContinueWith, чтобы организовать какое-то подобие очереди задач:
    // .................................................
    Task th_Image3 = Task.FromResult(0);
    // .................................................
    th_Image3 = th_Image3.ContinueWith(() => 
    {
        // Отображение GIF
    });


    В общем много чего можно сделать, проще всего не изобретать велосипед и взять готовое решение.
    Ответ написан
  • Каким образом можно заставить программу отрисовывать объекты по порядку через определённый интервал времени?

    gdt
    @gdt
    Программист
    У вас проблема из-за того, что вы всё время замораживаете основной поток (который и должен всё отрисовывать). И делаете всё в конструкторе, когда форму ещё никто не показал даже.
    Попробуйте переделать ваш drawTPointElement так:
    public async Task drawTPointElement(TPoint _rectangle)
    {
        Canvas.SetLeft(_rectangle.getPoint(), _rectangle.getXCoord());
        Canvas.SetTop(_rectangle.getPoint(), _rectangle.getYCoord());
        await Task.Delay(1000);
        mainCanvas.Children.Add(_rectangle.getPoint());
    }


    А в Main завернуть цикл в Task.Run вот так:
    Task.Run(async () =>
    {
        for (int i = 0; i <=5; i++)
        {
            TPoint point = new TPoint(5, i, 1, Brushes.Red);
            await drawTPointElement(point);
        }
    });


    Единственное что у вас скорее всего с таким подходом будут ошибки из-за того, что добавление в Children может происходить из другого потока, для этого можно обернуть mainCanvas.Children.Add(_rectangle.getPoint()); в что-то по типу Dispatcher.Invoke
    Ответ написан
  • Как запустить python код в WPF C#?

    gdt
    @gdt
    Программист
    Попробуйте IronPython, вот тут Run a particular Python function in C# with IronPython кажется ответ как раз на ваш вопрос, с примером кода.
    Ответ написан
    2 комментария