WPF ToggleButton渲染行为不正确

3
这里发生了什么事情,如何进行解决?
1. 点击MyToggleButton。现在它看起来像立即按下(选中)。 2. 同时,MyToggleButton_Checked处理程序禁用了MyToggleButton。 3. 现在按下非切换按钮“启用”。我们看到什么?MyToggleButton看起来像是已启用。好的。但等一下,现在它看起来像未按下!为什么?
XAML:
<StackPanel>

    <ToggleButton x:Name="MyToggleButton" Content="MyToggleButton" Checked="MyToggleButton_Checked"/>

    <TextBlock Text="{Binding IsChecked, ElementName=MyToggleButton}" Margin="0,4"/>

    <Button Name="EnableButton" Content="Enable" Click="EnableButton_Click"/>
    <Button Name="DisableButton" Content="Disable" Click="DisableButton_Click"/>

</StackPanel>

代码后台:

void MyToggleButton_Checked(object sender, RoutedEventArgs e)
{
    MyToggleButton.IsEnabled = false;
}


void EnableButton_Click(object sender, RoutedEventArgs e)
{
    MyToggleButton.IsEnabled = true;
}

void DisableButton_Click(object sender, RoutedEventArgs e)
{
    MyToggleButton.IsEnabled = false;
}

更新:

目前唯一可能的解决方法是:

void EnableButton_Click(object sender, RoutedEventArgs e)
{
    MyToggleButton.IsEnabled = true;

    var controlTemplate = MyToggleButton.Template;

    var buttonChrome = (Microsoft.Windows.Themes.ButtonChrome)controlTemplate.FindName("Chrome", MyToggleButton);

    buttonChrome.RenderPressed = false;

    buttonChrome.RenderPressed = true;
}

还有其他的吗?

更新2:

另一个解决方法是:

void EnableButton_Click(object sender, RoutedEventArgs e)
{
    MyToggleButton.IsEnabled = true;

    var controlTemplate = MyToggleButton.Template;
    MyToggleButton.Template = null;
    MyToggleButton.Template = controlTemplate;
}

但是在模板替换的瞬间,控件会闪烁。


看起来效果并没有在所有的机器上都出现。我的电脑是Windows 7专业版64位.NET 4,效果仍然存在。 - frtnum
效果取决于活动主题。至少在我的机器上是这样的。经典主题的工作正常。简单主题和Aero主题无法正常工作。这是我录制的视频,整个上传大小为3.1 Mb:http://screencast.com/t/KLCIwo9whs - frtnum
1个回答

6

这是我对这个问题的解决方案,这里有一个视频,使用方法:

<StackPanel>
    <ToggleButton x:Name="MyToggleButton" Content="MyToggleButton" Checked="MyToggleButton_Checked"
                    l:CorrectToggleButtonCheckedEnableBehavior.IsActive="True"/>
    <Button Name="EnableButton" Content="Enable" Click="EnableButton_Click"/>
</StackPanel>

以及附加的行为源代码:

public static class CorrectToggleButtonCheckedEnableBehavior
{
    public static bool GetIsActive(ToggleButton toggleButton)
    {
        return (bool)toggleButton.GetValue(IsActiveProperty);
    }

    public static void SetIsActive(ToggleButton toggleButton, bool value)
    {
        toggleButton.SetValue(IsActiveProperty, value);
    }

    public static readonly DependencyProperty IsActiveProperty =
        DependencyProperty.RegisterAttached("IsActive", typeof(bool), typeof(CorrectToggleButtonCheckedEnableBehavior),
        new UIPropertyMetadata(false, OnIsActiveChanged));

    static void OnIsActiveChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var toggleButton = (ToggleButton)d;

        if (GetIsActive(toggleButton))
        {
            toggleButton.IsEnabledChanged += new DependencyPropertyChangedEventHandler(ToggleButton_IsEnabledChanged);
        }
        else
        {
            toggleButton.IsEnabledChanged -= new DependencyPropertyChangedEventHandler(ToggleButton_IsEnabledChanged);
        }
    }

    static void ToggleButton_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        var toggleButton = (ToggleButton)sender;

        if (toggleButton.IsEnabled && (toggleButton.IsChecked ?? false))
        {
            Invalidate(toggleButton);
        }
    }

    static void Invalidate(ToggleButton toggleButton)
    {
        var controlTemplate = toggleButton.Template;
        toggleButton.Template = null;
        toggleButton.Template = controlTemplate;
    }
}

这正是我和我的同事们长期渴望寻找的!我向您表示最衷心的感谢。 - user4134476

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接