wpf-18161-mvvm-framework-services-predefined-set-taskbarbuttonservice.md
TaskbarButtonService is a ITaskbarButtonService implementation that allows you to customize an application taskbar button.
The image below demonstrates possible variants of taskbar button customization.
Assume that you need to dynamically animate a progress bar or modify the taskbar button background to, for instance, set it to red (error), yellow (pause), etc. To accomplish this task, you can use the TaskbarButtonService class.
Define the TaskbarButtonService in the Interaction.Behaviors collection.
<UserControl x:Class="DXSampleTaskbarButtonService.View.MainView"
...
xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm"
xmlns:ViewModel="clr-namespace:DXSampleTaskbarButtonService.ViewModel"
DataContext="{dxmvvm:ViewModelSource Type={x:Type ViewModel:MainViewModel}}">
...
<dxmvvm:Interaction.Behaviors>
<dxmvvm:TaskbarButtonService ProgressValue="{Binding ProgressValue}" ProgressState="Normal" ... />
</dxmvvm:Interaction.Behaviors>
...
</UserControl>
The TaskbarButtonService defined in the code snippet above displays a progress bar which represents the View Model’s ProgressValue property value.
The TaskbarButtonService’s properties can be set from XAML, but since they’re meant to be updated at runtime, setting them directly in code often makes more sense.
To learn how to obtain the TaskbarButtonService if ViewModel is a POCO object, see Services in POCO objects. If it’s a ViewModelBase descendant, refer to Services in ViewModelBase descendants.
Suppose we have a POCO View Model defined in the following manner.
[POCOViewModel]
public class MainViewModel {
public virtual double ProgressValue { get; set; }
protected virtual ITaskbarButtonService TaskbarButtonService { get { return null; } }
public MainViewModel() {
ProgressValue = 0.5;
}
...
}
<POCOViewModel> _
Public Class MainViewModel
Public Overridable Property ProgressValue() As Double
Protected Overridable ReadOnly Property TaskbarButtonService() As ITaskbarButtonService
Get
Return Nothing
End Get
End Property
Public Sub New()
ProgressValue = 0.5
End Sub
...
End Class
In this case, you can add extra properties to the View Model and change the states of the TaskbarButtonServices states, depending on the newly added property values. Consider the following example.
[POCOViewModel]
public class MainViewModel {
public virtual string Description { get; set; }
public virtual double ProgressValue { get; set; }
[BindableProperty(OnPropertyChangedMethodName = "UpdateProgressState")]
public virtual bool IsNormalProgressState { get; set; }
[BindableProperty(OnPropertyChangedMethodName = "UpdateProgressState")]
public virtual bool IsPausedProgressState { get; set; }
[BindableProperty(OnPropertyChangedMethodName = "UpdateProgressState")]
public virtual bool IsErrorProgressState { get; set; }
[BindableProperty(OnPropertyChangedMethodName = "UpdateProgressState")]
public virtual bool IsIndetermintateProgressState { get; set; }
[BindableProperty(OnPropertyChangedMethodName = "UpdateProgressState")]
public virtual bool IsNoneProgressState { get; set; }
protected virtual ITaskbarButtonService TaskbarButtonService { get { return null; } }
public MainViewModel() {
Description = "Hello, World!";
ProgressValue = 0.5;
IsNormalProgressState = true;
}
protected void UpdateProgressState() {
if (TaskbarButtonService == null) return;
if (IsNormalProgressState)
TaskbarButtonService.ProgressState = TaskbarItemProgressState.Normal;
else if (IsPausedProgressState)
TaskbarButtonService.ProgressState = TaskbarItemProgressState.Paused;
else if (IsErrorProgressState)
TaskbarButtonService.ProgressState = TaskbarItemProgressState.Error;
else if (IsIndetermintateProgressState)
TaskbarButtonService.ProgressState = TaskbarItemProgressState.Indeterminate;
else if (IsNoneProgressState)
TaskbarButtonService.ProgressState = TaskbarItemProgressState.None;
else
throw new NotImplementedException();
}
}
<POCOViewModel> _
Public Class MainViewModel
Public Overridable Property Description() As String
Public Overridable Property ProgressValue() As Double
<BindableProperty(OnPropertyChangedMethodName := "UpdateProgressState")> _
Public Overridable Property IsNormalProgressState() As Boolean
<BindableProperty(OnPropertyChangedMethodName := "UpdateProgressState")> _
Public Overridable Property IsPausedProgressState() As Boolean
<BindableProperty(OnPropertyChangedMethodName := "UpdateProgressState")> _
Public Overridable Property IsErrorProgressState() As Boolean
<BindableProperty(OnPropertyChangedMethodName := "UpdateProgressState")> _
Public Overridable Property IsIndetermintateProgressState() As Boolean
<BindableProperty(OnPropertyChangedMethodName := "UpdateProgressState")> _
Public Overridable Property IsNoneProgressState() As Boolean
Protected Overridable ReadOnly Property TaskbarButtonService() As ITaskbarButtonService
Get
Return Nothing
End Get
End Property
Public Sub New()
Description = "Hello, World!"
ProgressValue = 0.5
IsNormalProgressState = True
ThumbnailClipMargin = 0
End Sub
Protected Sub UpdateProgressState()
If TaskbarButtonService Is Nothing Then
Return
End If
If IsNormalProgressState Then
TaskbarButtonService.ProgressState = TaskbarItemProgressState.Normal
ElseIf IsPausedProgressState Then
TaskbarButtonService.ProgressState = TaskbarItemProgressState.Paused
ElseIf IsErrorProgressState Then
TaskbarButtonService.ProgressState = TaskbarItemProgressState.Error
ElseIf IsIndetermintateProgressState Then
TaskbarButtonService.ProgressState = TaskbarItemProgressState.Indeterminate
ElseIf IsNoneProgressState Then
TaskbarButtonService.ProgressState = TaskbarItemProgressState.None
Else
Throw New NotImplementedException()
End If
End Sub
End Class
The resulting taskbar button is shown in the screenshot below.
To customize the thumb buttons of the taskbar, use the TaskbarButtonService.ThumbButtonInfos property.
<dxmvvm:TaskbarButtonService.ThumbButtonInfos>
<dxmvvm:TaskbarThumbButtonInfo ImageSource="{dx:DXImageOffice2013 Image=MoveUp_16x16.png}" Command="{Binding IncereaseProgressCommand}"/>
<dxmvvm:TaskbarThumbButtonInfo ImageSource="{dx:DXImageOffice2013 Image=MoveDown_16x16.png}" Command="{Binding DecreaseProgressCommand}"/>
</dxmvvm:TaskbarButtonService.ThumbButtonInfos>
The TaskbarThumbButtonInfo class implements the functionality of an individual button that can be displayed within the thumb button of the taskbar.
TaskbarThumbButtonInfo provides the following properties.
If you need to call a user’s attention to a relevant section of the application window, use the TaskbarButtonService.ThumbnailClipMargin property to control the window clipping of the thumbnail image and handle the TaskbarButtonService.ThumbnailClipMarginCallback event raised when the window is resized.
The following image is an example of clipping. The original window thumbnail is on the left and the clipped version is on the right.
To show an icon over the taskbar button, use the TaskbarButtonService.OverlayIcon property.
<UserControl x:Class="DXSampleTaskbarButtonService.View.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm"
xmlns:ViewModel="clr-namespace:DXSampleTaskbarButtonService.ViewModel"
mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"
DataContext="{dxmvvm:ViewModelSource Type={x:Type ViewModel:MainViewModel}}">
<dxmvvm:Interaction.Behaviors>
<dxmvvm:TaskbarButtonService Description="{Binding Description}" ProgressValue="{Binding ProgressValue}" ProgressState="Normal">
<dxmvvm:TaskbarButtonService.ThumbButtonInfos>
<dxmvvm:TaskbarThumbButtonInfo Description="Increase progress value" ImageSource="{dx:DXImageOffice2013 Image=MoveUp_16x16.png}" Command="{Binding IncreaseProgressCommand}"/>
<dxmvvm:TaskbarThumbButtonInfo Description="Decrease progress value" ImageSource="{dx:DXImageOffice2013 Image=MoveDown_16x16.png}" Command="{Binding DecreaseProgressCommand}"/>
</dxmvvm:TaskbarButtonService.ThumbButtonInfos>
</dxmvvm:TaskbarButtonService>
</dxmvvm:Interaction.Behaviors>
<Grid x:Name="LayoutRoot" Background="White" Margin="2">
<StackPanel>
<TextBlock Text="Description:"/>
<TextBox Text="{Binding Description, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Text="Progress value:" Grid.Row="1" Grid.Column="0"/>
<Slider Minimum="0" Maximum="1" Value="{Binding ProgressValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center"/>
<TextBlock Text="Progress state:"/>
<GroupBox Header="Progress state">
<StackPanel Orientation="Vertical">
<RadioButton Content="Normal" GroupName="progressState" IsChecked="{Binding IsNormalProgressState, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<RadioButton Content="Paused" GroupName="progressState" IsChecked="{Binding IsPausedProgressState, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<RadioButton Content="Error" GroupName="progressState" IsChecked="{Binding IsErrorProgressState, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<RadioButton Content="Indetermintate" GroupName="progressState" IsChecked="{Binding IsIndetermintateProgressState, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<RadioButton Content="None" GroupName="progressState" IsChecked="{Binding IsNoneProgressState, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
</GroupBox>
</StackPanel>
</Grid>
</UserControl>
using DevExpress.Mvvm;
using DevExpress.Mvvm.POCO;
using DevExpress.Mvvm.DataAnnotations;
using System;
using System.Windows.Shell;
namespace DXSampleTaskbarButtonService.ViewModel {
[POCOViewModel]
public class MainViewModel {
private int ThumbnailClipMargin { get; set; }
public virtual string Description { get; set; }
public virtual double ProgressValue { get; set; }
[BindableProperty(OnPropertyChangedMethodName = "UpdateProgressState")]
public virtual bool IsNormalProgressState { get; set; }
[BindableProperty(OnPropertyChangedMethodName = "UpdateProgressState")]
public virtual bool IsPausedProgressState { get; set; }
[BindableProperty(OnPropertyChangedMethodName = "UpdateProgressState")]
public virtual bool IsErrorProgressState { get; set; }
[BindableProperty(OnPropertyChangedMethodName = "UpdateProgressState")]
public virtual bool IsIndetermintateProgressState { get; set; }
[BindableProperty(OnPropertyChangedMethodName = "UpdateProgressState")]
public virtual bool IsNoneProgressState { get; set; }
protected virtual ITaskbarButtonService TaskbarButtonService { get { return null; } }
public MainViewModel() {
Description = "Hello, World!";
ProgressValue = 0.5;
IsNormalProgressState = true;
ThumbnailClipMargin = 0;
}
protected void UpdateProgressState() {
if (TaskbarButtonService == null) return;
if (IsNormalProgressState)
TaskbarButtonService.ProgressState = TaskbarItemProgressState.Normal;
else if (IsPausedProgressState)
TaskbarButtonService.ProgressState = TaskbarItemProgressState.Paused;
else if (IsErrorProgressState)
TaskbarButtonService.ProgressState = TaskbarItemProgressState.Error;
else if (IsIndetermintateProgressState)
TaskbarButtonService.ProgressState = TaskbarItemProgressState.Indeterminate;
else if (IsNoneProgressState)
TaskbarButtonService.ProgressState = TaskbarItemProgressState.None;
else
throw new NotImplementedException();
}
public void IncreaseProgress() {
if (ProgressValue < 1) {
ProgressValue += 0.1d;
}
}
public void DecreaseProgress() {
if (ProgressValue > 0) {
ProgressValue -= 0.1d;
}
}
}
}
Imports DevExpress.Mvvm
Imports DevExpress.Mvvm.POCO
Imports DevExpress.Mvvm.DataAnnotations
Imports System
Imports System.Windows.Shell
Namespace DXSampleTaskbarButtonService.ViewModel
<POCOViewModel> _
Public Class MainViewModel
Private Property ThumbnailClipMargin() As Integer
Public Overridable Property Description() As String
Public Overridable Property ProgressValue() As Double
<BindableProperty(OnPropertyChangedMethodName := "UpdateProgressState")> _
Public Overridable Property IsNormalProgressState() As Boolean
<BindableProperty(OnPropertyChangedMethodName := "UpdateProgressState")> _
Public Overridable Property IsPausedProgressState() As Boolean
<BindableProperty(OnPropertyChangedMethodName := "UpdateProgressState")> _
Public Overridable Property IsErrorProgressState() As Boolean
<BindableProperty(OnPropertyChangedMethodName := "UpdateProgressState")> _
Public Overridable Property IsIndetermintateProgressState() As Boolean
<BindableProperty(OnPropertyChangedMethodName := "UpdateProgressState")> _
Public Overridable Property IsNoneProgressState() As Boolean
Protected Overridable ReadOnly Property TaskbarButtonService() As ITaskbarButtonService
Get
Return Nothing
End Get
End Property
Public Sub New()
Description = "Hello, World!"
ProgressValue = 0.5
IsNormalProgressState = True
ThumbnailClipMargin = 0
End Sub
Protected Sub UpdateProgressState()
If TaskbarButtonService Is Nothing Then
Return
End If
If IsNormalProgressState Then
TaskbarButtonService.ProgressState = TaskbarItemProgressState.Normal
ElseIf IsPausedProgressState Then
TaskbarButtonService.ProgressState = TaskbarItemProgressState.Paused
ElseIf IsErrorProgressState Then
TaskbarButtonService.ProgressState = TaskbarItemProgressState.Error
ElseIf IsIndetermintateProgressState Then
TaskbarButtonService.ProgressState = TaskbarItemProgressState.Indeterminate
ElseIf IsNoneProgressState Then
TaskbarButtonService.ProgressState = TaskbarItemProgressState.None
Else
Throw New NotImplementedException()
End If
End Sub
Public Sub IncreaseProgress()
If ProgressValue < 1 Then
ProgressValue += 0.1R
End If
End Sub
Public Sub DecreaseProgress()
If ProgressValue > 0 Then
ProgressValue -= 0.1R
End If
End Sub
End Class
End Namespace