Reputation: 71
I am new to WPF and have not been able to find the solution to this yet.
We are trying to make a UserControl that provides a progressbar that will change its style as the percentage goes up (basically red when like less then 50%, yellow to 30%, etc.)
The control seems to work exceot for the style getting updated. When the window is first brought up the value is always 0 even if the progressbar is being started at 50% or so. To me it seems I have messed up the PropertyChanged code or not connected the data up right somewhere. Here is the code so far:
XAML file comsuming the UserControl (TaskListStatus.xaml)
<ssw:ColoredProgressBar x:Name="pbCompleted" Value="{Binding PercentCompleted}" Height="40"/>
ColoredProgressBar.xaml:
<UserControl.Resources>
<this:ProgressBarStyleConverter x:Key="pbStyleConverter"/>
<!-- Progress Bar Styles-->
........
</UserControl.Resources>
<Grid>
<ProgressBar x:Name="pb" Value="{Binding Path=Value, ElementName=coloredBar}">
<ProgressBar.Style>
<Binding Converter="{StaticResource pbStyleConverter}"
RelativeSource="{RelativeSource Self}"/>
</ProgressBar.Style>
</ProgressBar>
</Grid>
ColoredProgressBar.xaml.cs
public partial class ColoredProgressBar : UserControl, INotifyPropertyChanged {
public ColoredProgressBar() {
InitializeComponent();
}
public static DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(double),
typeof(ColoredProgressBar), new PropertyMetadata(null));
public double Value {
get { return Convert.ToDouble(GetValue(ValueProperty)); }
set {
SetValue(ValueProperty, value);
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs("Value"));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
ProgressBarStyleConverter.cs
public class ProgressBarStyleConverter : IValueConverter {
private const int RED_CUTOFF = 40;
private const int YELLOW_CUTOFF = 100;
private enum ProgressBarColor {
Green,
Yellow,
Red
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
FrameworkElement targetElement = value as FrameworkElement;
double progressBarValue = ((ProgressBar)targetElement).Value;
string styleName = "AeroProgressBarStyle";
ProgressBarColor color;
if (progressBarValue < RED_CUTOFF) {
color = ProgressBarColor.Red;
} else if (progressBarValue < YELLOW_CUTOFF) {
color = ProgressBarColor.Yellow;
} else {
color = ProgressBarColor.Green;
}
switch (color) {
case ProgressBarColor.Green:
styleName = "AeroProgressBarStyle"; break;
case ProgressBarColor.Yellow:
styleName = "YellowAeroProgressBarStyle"; break;
case ProgressBarColor.Red:
styleName = "RedAeroProgressBarStyle"; break;
}
return (Style)targetElement.TryFindResource(styleName);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
return null;
}
}
If anyone can help it would be greatly appreciated.
Upvotes: 2
Views: 432
Reputation: 71
So far this is the way we have gotten it to work. I am not 100% sure this is the ideal way but it does work:
ColoredProgressBar.xaml:
<UserControl.Resources>
<this:ProgressBarStyleConverter x:Key="pbStyleConverter"/>
<!-- Progress Bar Styles-->
........
</UserControl.Resources>
<Grid>
<ProgressBar x:Name="pb" Value="{Binding Path=Value, ElementName=coloredBar}">
<ProgressBar.Style>
<MultiBinding Converter="{StaticResource pbStyleConverter}">
<Binding RelativeSource="{RelativeSource Self}" />
<Binding ElementName="coloredBar" Path="Value" />
</MultiBinding>
</ProgressBar.Style>
</ProgressBar>
</Grid>
We could not figure out how to get the binding down to a single binding. The reason we have to pass in Self is because that is where all of the temples are defined for setting up the color. I tried passing Self in as a ConverterParameter but I could never seem to get it to work. So by passing it in as a MultiBinding we can get to self and the temples defined there and since value is passed in, when value updates, it updates the temple of the progressbar.
Upvotes: 1
Reputation: 1234
Bind the style to the Value property of the ProgressBar rather than the ProgressBar itself. So add a Path=Value attribute to the binding, and modify the converter code accordingly.
Upvotes: 0