WPF Progress bar - wpf

WPF: I have a Problem in Progressbar i want it to show when the operation is not finished and when my operation is finished it will hide. Please show me understandable example so i can apply it to my work. Thanks in advance!

you can do that in different scenarios.
using triggers, (I'd prefer that)
<ProgressBar Maximum="100" Margin="10,107,232,168" Value="0" Name="progr">
<ProgressBar.Resources>
<Style TargetType="{x:Type ProgressBar}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Value}" Value="100">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ProgressBar.Resources>
</ProgressBar>
Using converters
<Grid>
<Grid.Resources>
<delWpf:VisibilityConverter x:Key="conv"/>
</Grid.Resources>
<ProgressBar Name="prog2" Minimum="0" Maximum="100"
Value="{Binding CurrentIndex, UpdateSourceTrigger=PropertyChanged}"
Visibility="{Binding RelativeSource={RelativeSource Self}, Path=Value, Mode=OneWay, Converter={StaticResource conv}}" />
</Grid>
and converter
public class VisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return Math.Abs((double)value - 100) < 0.001 ? Visibility.Hidden : Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

You might use Extended WPF Toolkit which has a BusyIndicator control,
http://wpftoolkit.codeplex.com/wikipage?title=BusyIndicator
Samples are included in the download.
For your information, Microsoft introduces BusyIndicator in Silverlight first (but fails to ship one for WPF) as a replacement of progress bar.

Related

How to OR a local bool with a viewmodel bool and bind to visibility property

I have the following XAML in a usercontrol that loads a series of gauge usercontrols:
<ItemsControl ItemsSource="{Binding InstanceViper.Gauges}" Grid.Row="7" Grid.ColumnSpan="4">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Name="GaugePanel" VerticalAlignment="Bottom" HorizontalAlignment="Left" Orientation="Horizontal">
</WrapPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:Gauge DataContext="{Binding}" AlwaysShowGauge="False"></local:Gauge>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I am passing in a flag that determines if the gauge should be displayed always or only when in alarm. Now in gauge xaml I want to do something like the following to determine if it should be displayed:
<Border Name="MainBorder" Visibility="{Binding (ShowAlarm || AlwaysShowGauge) ,Converter={StaticResource BooleanToVisibilityConverter}}">
Problem is that the ShowAlarm property is from the gauge viewmodel and AlwaysShowGauge is a local property being passed in in the data template. The ShowAlarm is dynamic but AlwaysShowGauge won't change once set. How can I accomplish this?
Its hard to tell where your border comes from, and where the one of the bindings come from. But you can control the Binding flow, that's not a problem. The main problem is how do you multi trigger, below is just a start. Once you see how you can multi trigger, then, you can play with the binding, either control the flow from one view model or view properties, or play with paths from different sources, to do that is you might have to put the following sample in the DataTemplate and use SourceName and TargetName.. But again, it's hard to tell where the border is.
<converters:OrMultiConverter x:Key="Or" />
<Style x:Key="MainBorderStyle" TargetType="{x:Type Border}">
<Setter Property="Visibility" Value="Hidden" />
<Style.Triggers>
MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Value="True">
<Condition.Binding>
<MultiBinding Converter="{StaticResource Or}">
<Binding Path="ShowAlarm"/>
<Binding Path="AlwaysShowGaug"/>
</MultiBinding>
</Condition.Binding>
</Condition>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Visibility" Value="Visible"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</Style.Triggers>
public class OrMultiConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Any(value => value == null || value == DependencyProperty.UnsetValue))
return false;
var boolValues = values.Cast<bool>();
var result = boolValues.Any(b => b);
return result;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

AutoHide Progressbar with StyleTriggers

I would like to hide a progressbar in WPF using databinding. Whenever a property is 0, the progressbar should hide: I try the following code
(Info: My current datacontext is a class that holds an integer property 'CurrentIndex')
<ProgressBar Minimum="0" Maximum="100" Value="{Binding CurrentIndex, UpdateSourceTrigger=PropertyChanged}" Visibility="Visible">
<ProgressBar.Style>
<Style TargetType="{x:Type ProgressBar}">
<Style.Triggers>
<DataTrigger Binding="{Binding CurrentIndex}" Value="0">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ProgressBar.Style>
</ProgressBar>
What is wrong with this code? Why does the progressbar still show up when the CurrentIndex is 0? (in the model behind, the value of 'CurrentIndex' is 0 by default, when the control is loaded)
DP precedence, do not set Visibility on the control itself (local value > style).
Other way to use visibility binding and a converter:
<Grid>
<Grid.Resources>
<App:VisibilityConverter x:Key="VisibilityConverter" />
</Grid.Resources>
<ProgressBar Minimum="0" Maximum="100" Value="{Binding CurrentIndex, UpdateSourceTrigger=PropertyChanged}"
Visibility="{Binding CurrentIndex, Mode=OneWay, Converter={StaticResource VisibilityConverter}}" />
</Grid>
The converter code (VisibilityConverter.cs):
public class VisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (int)value == 0 ? Visibility.Hidden : Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Your XAML was almost right!
Define your progressbar as you did:
<ProgressBar Minimum="0"
Maximum="100"
Value="{Binding CurrentIndex, UpdateSourceTrigger=PropertyChanged}"
Name="MyAutoHidingProgressBar" />
Don't forget to add the Name property AND do not set the Visibility here.
It will always override what is set in your Style.
Then define a Style as normal in your <Window.Resources>
<Window.Resources>
<Style TargetType="ProgressBar" x:Key="MyAutoHidingProgressBarStyle">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=MyAutoHidingProgressBar, Path=Value}" Value="0">
<Setter Property="Visibility" Value="Hidden"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
What this is basically doing is to check the Value of the progressbar itself, rather than your binding.
As a last step add the Style to your progressbar:
Style="{StaticResource MyAutoHidingProgressBarStyle}"
Now your ProgressBar will auto hide if its Value is 0.
You can also easily add a Trigger to hide it if its full.

Enable TextBox when ListViewItem is selected in WPF (databinding)

How can i enable/disable a TextBox with DataBinding in WPF when a ListViewItem is (not) selected?
I have created a converter class:
public class BoolConvert : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value == null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new Exception("The method or operation is not implemented.");
}
}
and added the property to the TextBox:
IsEnabled="{Binding SelectedItem, ElementName=listViewCards, Converter={StaticResource BoolConvert}}"
but i have a XamlParseException becouse he can´t find the class :-(
You could alternately use a style trigger on the TextBox, eliminating the need for a ValueConverter:
<TextBox>
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="IsEnabled" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=lvItems, Path=SelectedItem}" Value="{x:Null}">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<ListView Name="lvItems" .../>
You can bind the IsEnabled property on the TextBox to the SelectedItem property on the ListView. Then you'll need a converter (an implementation of IValueConverter) to convert selected values into boolean values.
<TextBox IsEnabled="{Binding SelectedItem, ElementName=listView, Converter={StaticResource MyConverter}}"/>
<ListView x:Name="listView" .../>
Then, in your converter:
public object Convert(object value, ...)
{
return value == null;
}
ListViewItem in ListView :
Enable if Selected.
Try the following:
<ListViewItem Margin="5" Background="AliceBlue">
<TextBox Margin="5" Text="Lösung SECHS"
IsEnabled="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListViewItem}}, Path=IsSelected}"/>
</ListViewItem>

Simple WPF IValueConverter and DataTrigger not working together

I've been having trouble using a value converter with a data trigger. In some of my code it seems like the DataTrigger's Path is being applied to the root element, rather than the element which the style applies to.
I created a simple test case, and I don't understand its behavior. I'm expecting the Button to turn red or blue depending on which value is being fed to the DataTrigger's converter, but the Button isn't being affected at all!
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SimpleWpfApplication"
x:Class="SimpleWpfApplication.SimpleUserControl"
ToolTip="UserControl ToolTip">
<UserControl.Resources>
<local:SimpleConverter x:Key="SimpleConverter" />
</UserControl.Resources>
<Button ToolTip="Button ToolTip">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<DataTrigger
Binding="{Binding Path=ToolTip, Converter={StaticResource SimpleConverter}}"
Value="Button ToolTip">
<Setter Property="Background" Value="Red" />
</DataTrigger>
<DataTrigger
Binding="{Binding Path=ToolTip, Converter={StaticResource SimpleConverter}}"
Value="UserControl ToolTip">
<Setter Property="Background" Value="Blue" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</UserControl>
And a simple converter:
class SimpleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new InvalidOperationException("SimpleConverter is a OneWay converter.");
}
}
Why isn't Convert being called? Why doesn't the Button turn red or blue?
Found the answer in another StackOverflow question: What’s wrong with my datatrigger binding?
The answer is to add RelativeSource={RelativeSource Self} to the binding:
<DataTrigger Binding="{Binding Path=ToolTip,
RelativeSource={RelativeSource Self},
Converter={StaticResource SimpleConverter}}" />

WPF Datatrigger not firing when expected

I have the following XAML:
<TextBlock Text="{Binding ElementName=EditListBox, Path=SelectedItems.Count}" Margin="0,0,5,0"/>
<TextBlock Text="items selected">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=EditListBox, Path=SelectedItems.Count}" Value="1">
<Setter Property="TextBlock.Text" Value="item selected"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
The first text block happily changes with SelectedItems.Count, showing 0,1,2, etc. The datatrigger on the second block never seems to fire to change the text.
Any thoughts?
Alternatively, you could replace your XAML with this:
<TextBlock Margin="0,0,5,0" Text="{Binding ElementName=EditListBox, Path=SelectedItems.Count}"/>
<TextBlock>
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Text" Value="items selected"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=EditListBox, Path=SelectedItems.Count}" Value="1">
<Setter Property="Text" Value="item selected"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
Converters can solve a lot of binding problems but having a lot of specialized converters gets very messy.
The DataTrigger is firing but the Text field for your second TextBlock is hard-coded as "items selected" so it won't be able to change. To see it firing, you can remove Text="items selected".
Your problem is a good candidate for using a ValueConverter instead of DataTrigger. Here's how to create and use the ValueConverter to get it to set the Text to what you want.
Create this ValueConverter:
public class CountToSelectedTextConverter : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if ((int)value == 1)
return "item selected";
else
return "items selected";
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
Add the namespace reference to your the assembly the converter is located:
xmlns:local="clr-namespace:ValueConverterExample"
Add the converter to your resources:
<Window.Resources>
<local:CountToSelectedTextConverter x:Key="CountToSelectedTextConverter"/>
</Window.Resources>
Change your second textblock to:
<TextBlock Text="{Binding ElementName=EditListBox, Path=SelectedItems.Count, Converter={StaticResource CountToSelectedTextConverter}}"/>

Resources