WPF:按下按钮时更改选项卡 Header 字体颜色

WPF: Change Tab Header Font Color When Button is Pressed

我正在开发一个有多个选项卡的程序,每个选项卡都包含多个按钮,单击这些按钮会在 BackgroundWorker object 中执行 SQL 调用。单击一个按钮后,只要 SQL 进程正常运行,其他按钮就会被禁用

因为其中一些 SQL 调用可能需要一个多小时,所以我使用 BackgroundWorker 以便 GUI 仍然响应用户输入(即更改选项卡),但按钮被禁用,直到当前 SQL 进程已完成。

功能请求之一是将当前所选选项卡的 header 字体颜色更改为绿色(通常为黑色),以指示此选项卡中的其中一个按钮是启动当前 运行 SQL。 SQL 完成后,字体颜色应 return 为黑色。

是否可以用 style/datatrigger 做到这一点?我想不出一种方法可以在按下按钮后将样式应用于当前选定的选项卡,然后如果我在后台工作人员仍在工作时切换选项卡则保持该颜色。

我对此的另一个想法是,每当我单击按钮时通过代码更改选项卡 header 字体颜色的方法,然后在后台工作人员完成后将其更改回来,但这需要更新所有ButtonClicked() 方法。

我也愿意接受任何其他解决方案。

我知道 async/await 功能,但无法更改使用 BackgroundWorker 执行 SQL 的代码,因此请不要建议使用 async/await。

绑定到选项卡的 ViewModel 实例可能有一个名为 运行 的 属性。

public bool IsRunning { get; set; }

使用转换器将背景颜色绑定到背景 属性。 http://wpftutorial.net/ValueConverters.html

根据 true/false 转换器将 return 一种颜色。您甚至可以将颜色作为参数传递给绑定。 在执行查询之前将其设置为 true,完成后将其设置为 true。

myVM.IsRunning=true;
executeQuery();
myVM.IsRunning=false;

这样的东西应该是你想要的:

<TabControl ItemsSource="{Binding Tabs}">

    <TabControl.ItemTemplate>
        <DataTemplate>

            <TextBlock Text="{Binding TabHeader}">
                <TextBlock.Style>
                    <Style TargetType="TextBlock">

                        <Setter Property="Foreground" Value="Black"/>

                        <Style.Triggers>
                            <DataTrigger Binding="{Binding IsWorking}" Value="True">

                                <Setter Property="Foreground" Value="Green"/>

                            </DataTrigger>
                        </Style.Triggers>

                    </Style>
                </TextBlock.Style>
            </TextBlock>

        </DataTemplate>
    </TabControl.ItemTemplate>

</TabControl>

Tabs 集合中每个项目的视图模型如下所示:

public class TabViewModel
{
    public string TabHeader { get; set; }
    public bool IsWorking { get; set; }
}

显然,视图模型应该实现通知 属性 已更改。

试试

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Background="LightGray" 
    Title="Window1" Height="350" Width="700" >
    <Window.Resources>
        <Style x:Key="myHeaderStyle" TargetType="{x:Type TextBlock}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type TabItem}}, Path=DataContext}" Value="True">
                    <Setter Property="Foreground" Value="Green" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
        <DataTemplate x:Key="myHeader">
            <TextBlock Text="{Binding}" Style="{DynamicResource myHeaderStyle}" />
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <TabControl>
            <TabItem x:Name="FirstTab" Header="First tab" HeaderTemplate="{DynamicResource myHeader}" DataContext="{Binding FirstTabSelected}">
                <Button Click="Button_Click">
                    First button
                </Button>
            </TabItem>
            <TabItem Header="Second tab" HeaderTemplate="{DynamicResource myHeader}"  DataContext="{Binding SecondTabSelected}">
                <Button Click="Button_Click_1">
                    Second button
                </Button>
            </TabItem>
        </TabControl>
    </Grid>
</Window>

和代码隐藏

[ImplementPropertyChanged]
public partial class MainWindow : Window
{
    public bool FirstTabSelected { get; set; }
    public bool SecondTabSelected { get; set; }

    public MainWindow()
    {
        FirstTabSelected = true;
        SecondTabSelected = true;
        InitializeComponent();

        this.DataContext = this;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        FirstTabSelected = !FirstTabSelected;
    }

    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        SecondTabSelected = !SecondTabSelected;
    }
}

我正在使用 Fody propertyChanged,所以我不需要手动实施 INotifyPropertyChanged