我正在开发一个具有多个选项卡的程序,每个选项卡都包含多个按钮,单击这些按钮时会在 BackgroundWorker 对象中执行 SQL 调用。 单击按钮后,只要SQL进程正常工作,其他按钮就会被禁用
由于其中一些SQL调用可能需要一个小时以上,因此我正在使用BackgroundWorkers,以便GUI仍然响应用户输入(即更改选项卡),但在当前SQL进程完成之前,按钮将被禁用。
其中一个功能请求是将当前所选选项卡的标题字体的颜色更改为绿色(通常为黑色),以指示此选项卡中的某个按钮是启动当前运行的 SQL 的按钮。 SQL 完成后,字体颜色应恢复为黑色。
是否可以使用样式/数据触发器执行此操作? 一旦按下按钮,我想不出将样式应用于当前所选选项卡的方法,然后在后台工作人员仍在工作时切换选项卡时保持该颜色。
我对此的另一个想法是一种方法,每当我单击按钮时,该方法都会通过代码更改选项卡标题字体颜色,然后在后台工作线程完成后将其更改回来,但这需要更新所有 ButtonClicked() 方法。
我也对任何其他解决方案持开放态度。
我知道 async/await 功能,但无法更改使用 BackgroundWorker 执行 SQL 的代码,所以请不要建议使用 async/await。
这样的东西应该是你想要的:
<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; }
}
显然,视图模型应该实现通知属性已更改。
绑定到选项卡的 ViewModel 实例可能具有一个名为"正在运行"的属性。
public bool IsRunning { get; set; }
使用转换器将背景色绑定到背景属性。http://wpftutorial.net/ValueConverters.html
根据真/假,转换器将返回颜色。您甚至可以将颜色作为绑定中的参数传递。在执行查询之前将其设置为 true,完成后将其设置为 true。
myVM.IsRunning=true;
executeQuery();
myVM.IsRunning=false;
尝试使用
<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
。