Enable/Disable Combobox if label content changed - wpf

Is it possible to enable/disable the combobox if the label has content in the xaml? (I am looking for a xaml solution.)
<Label x:Name="lbl_AusgewählteEmail" HorizontalAlignment="Left"
Margin="37,132,0,0" VerticalAlignment="Top" Width="607"
Content="{Binding ElementName=combx_UnzustellbarMailAuswahl, Path=SelectedItem}"/>
<ComboBox x:Name="combx_Auswahl" HorizontalAlignment="Left"
Margin="37,219,0,0" VerticalAlignment="Top" Width="318"/>

In pure XAML, no. You can however use an IValueConverter to turn that string into a boolean:
public class NonEmptyStringToBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is string)
return !String.IsNullOrEmpty((string) value);
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return DependencyProperty.UnsetValue;
}
}
<Window.Resources>
<yourNameSpace:NonEmptyStringToBooleanConverter x:Key="StringToBool"/>
</Window.Resources>
<Label x:Name="lbl_AusgewählteEmail" HorizontalAlignment="Left"
Margin="37,132,0,0" VerticalAlignment="Top" Width="607"
Content="{Binding ElementName=combx_UnzustellbarMailAuswahl, Path=SelectedItem}"/>
<ComboBox x:Name="combx_Auswahl" HorizontalAlignment="Left"
Margin="37,219,0,0" VerticalAlignment="Top" Width="318"
IsEnabled="{Binding ElementName=combx_UnzustellbarMailAuswahl, Path=SelectedItem, Converter={StaticResource StringToBool}"/>
You could potentially also do this via a Style but that would be a bit weird to be honest. For the sake of completeness:
Include the following namespace at the top of your containing control/window:
xmlns:system="clr-namespace:System;assembly=mscorlib"
<ComboBox.Style>
<Style TargetType="ComboBox">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=combx_UnzustellbarMailAuswahl, Path=SelectedItem}" Value="{x:Static system:String.Empty}">
<Setter Property="IsEnabled" Value="False"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=combx_UnzustellbarMailAuswahl, Path=SelectedItem}" Value="{x:Null}">
<Setter Property="IsEnabled" Value="False"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ComboBox.Style>

Related

How to reference a resource image in converter?

I have a few images defined in my resource section of my UI :
<Window.Resources>
<!-- Converters -->
<loc:UserStatusToIconConverter x:Key="UserStatusToIconConverter" />
<!-- Images -->
<BitmapImage x:Key="ConnectIcon" UriSource="/WPFClient;component/Images/connect.png" />
<BitmapImage x:Key="ActiveIcon" UriSource="/WPFClient;component/Images/active.png" />
<BitmapImage x:Key="IdleIcon" UriSource="/WPFClient;component/Images/idle.png" />
<BitmapImage x:Key="AwayIcon" UriSource="/WPFClient;component/Images/away.png" />
<BitmapImage x:Key="UnknownIcon" UriSource="/WPFClient;component/Images/unknown.png" />
...
I would like to select one of these for a binding in my converter, I assume this would be more efficient than creating a new image each time (500 times) from the converter.
public class UserStatusToIconConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string userStatus = value.ToString();
string iconName = ...;
switch (userStatus)
{
case "Active":
// select ActiveIcon;
break;
case "Idle":
// select IdleIcon;
break;
case "Away":
...
break;
}
return iconName;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Here is where I use it :
<ListBox ItemsSource="{Binding Users}">
<ListBox.ItemTemplate>
<DataTemplate>
<DockPanel>
<Image Source="{Binding Status, Converter={StaticResource UserStatusToIconConverter}}" Height="16" Width="16" />
<TextBlock Text="{Binding Nick}" />
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I think you're better off using DataTemplate.Triggers in this case rather than a Converter:
<DataTemplate>
<DockPanel>
<Image x:Name="Img" Height="16" Width="16" />
<TextBlock Text="{Binding Nick}" />
</DockPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Status}" Value="Active">
<Setter TargetName="Img" Property="Source" Value="{StaticResource ActiveIcon}"/>
</DataTrigger>
<DataTrigger Binding="{Binding Status}" Value="Idle">
<Setter TargetName="Img" Property="Source" Value="{StaticResource IdleIcon}"/>
</DataTrigger>
<!-- And So on... -->
</DataTemplate.Triggers>
</DataTemplate>
You may just do the following in your Convert method:
return Application.Current.MainWindow.FindResource(iconName);

WPF Progress bar

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.

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>

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