Reputation: 377
What I want to do is place two controls at the same position/spot, to be specific a button that contains a ProgressBar inside of it and a button that contains a Icon, once the progress bar is full, I want to switch it to the button which has the icon, like a checkbox/toggle button, it has more than one state, when I change it, it changes the controls.
Image example of the controls:
OBS: The controls are in the title bar controls using MahApps
OBS2: I am using Material Design XAML, and Caliburn.Micro for awesome MVVM
XAML Example:
<Button FontSize="15"
FontWeight="Bold"
cal:Message.Attach="UpdateStatus"
ToolTip="Click here to show the update status."
Visibility="Visible">
<ProgressBar Style="{StaticResource MaterialDesignCircularProgressBar}"
Value="0"
IsIndeterminate="True"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Height="22"
Width="22" Foreground="White"/>
</Button>
<Button FontSize="15"
FontWeight="Bold"
cal:Message.Attach="Restart"
ToolTip="A update is scheduled, click here to restart the loader and apply the update."
Visibility="{Binding Path=RestartButtonVisibility, Mode=TwoWay}">
<materialDesign:PackIcon Height="22"
Width="22"
Kind="Cached"
FontWeight="Bold"/>
</Button>
Is it possible to acomplish that ? Is there a good way that is not spaghetti to accomplish it ?
Upvotes: 2
Views: 2090
Reputation: 1337
You could bind the first button's visibility to a property in VM like the second and make them mutually exclusive (one visible then other collapsed). Trigger the onpropertychanged at the end of progressbar completion and you should be good to go.
Upvotes: 0
Reputation: 118
To have two UI elements at the same spot, you can put them inside a Grid
. You just set them to the same row/column (or just don't set anything at all). Then, you'll probably need to implement a new IValueConverter
that does the trick.
First, a class somewhere in your local namespace:
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
.
.
.
public class MyValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
double v = (double)value;
if (v == 100) return Visibility.Visible;
return Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
//Not really necesary...
return 0.0;
}
}
This is a value converter. It is used with property bindings, like what you want to do.
And now, your XAML:
<!-- This should be atop... -->
<Window.Resources>
<local:MyValueConverter x:Key="ValueConverter1"/>
</Window.Resources>
.
.
.
<Grid>
<Button x:Name="Button1">
<ProgressBar x:Name="ProgressBar1" Value="50" Width="100" Height="8"/>
</Button>
<Button x:Name="Button2" Visibility="{Binding Value, ElementName=ProgressBar1, Converter={StaticResource ValueConverter1}}">
<StackPanel Orientation="Horizontal">
<Image Source="yourIcon"/>
<TextBlock Text="Label for your button"/>
</StackPanel>
</Button>
</Grid>
We use a value converter to bind the visibility of the second button so that, if the progress bar value is 100, the value given to the Visibility
property will be Visibility.Visible
, and vice-versa.
Upvotes: 1