<GroupBox x:Name="groupBox" Header="Operating System" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Height="74" Width="280">
<StackPanel>
<RadioButton GroupName="Os" Content="Windows 7 (64-bit)" IsChecked="True"/>
<RadioButton GroupName="Os" Content="Windows 7 (32-bit)" />
</StackPanel>
</GroupBox>
I have several radio button groups in my application
How can I access which one has been checked in the Code-Behind using C#?
Is it absolutely necessary to use x:Name= on each RadioButton or is there a better way?
Code samples always appreciated
Yes! There is a better way, its called binding. Outside of binding, you are pretty much stuck (I can imagine handling all the checked events separately, and assigning to an enum, but is that really better?)
For radio buttons, you would typically use an enum to represent all the possible values:
public enum OsTypes
{
Windows7_32,
Windows7_64
}
And then bind each of your radio buttons to a global "selected" property on your VM. You need a ValueEqualsConverter for this:
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value.Equals(parameter);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return ((bool)value) ? parameter : Binding.DoNothing;
}
And then your radio buttons look like:
<RadioButton Content="Windows 7 32-bit"
IsChecked= "{Binding CurrentOs,
Converter={StaticResource ValueEqualsConverter},
ConverterParameter={x:Static local:OsTypes.Windows7_32}}"
Of course, you have a property in your VM:
public OsTypes CurrentOs {get; set;}
No x:Name, complicated switch statements, or anything else. Nice, clean, and well designed. MVVM works with WPF, use it!
Related
I currently have a combobox in my WPF application, but it seems like there's some lag before the value is converted.
The value converter converts a UUID/GUID to a name, but what shows up on the combobox is first the UUID/GUID for a split second and then the name shows up.
Here's a boiled down version of my combobox:
<ComboBox x:Name="MyComboBox"
Text="{Binding Path=GUID, Converter={StaticResource GUIDToNameValueConverter}, Mode=OneWay}"
ItemTemplate="{StaticResource MyTemplate}"
Style="{StaticResource MyStyle}"
ItemsSource="{Binding Source={x:Static myNameSpace:MyItems}, Path=Items}"
SelectionChanged="MyChangedEventHandler">
</ComboBox>
Here's the general gist of my valueconverter:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string GUID = (string)value;
MyObject myObject = GetObjectById(GUID);
return myObject.name;
}
Essentially, I want to get rid of the split second display of the GUID before the actual name shows up. I'm unsure why the GUID event shows up since the converter takes care of converting that to a name.
Let me know if this is enough information to have this question answered, if not, please request more parts of my code!
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I have a question regarding running the same application in different "modes".
Basically, I want the app to be editable if you know what you're doing (e.g. you're an admin of sorts) but not if you're just using it.
I was thinking about making a bool/int value and make it hide show elements based on the mode. But is this the correct way? is there a better way to do this?
Thanks in advance!
You're right to have a single setting in the ViewModel that reflects the logical requirement. If there are only two options, it should be a boolean.
You probably have to think carefully about which controls need to be disabled, hidden or read-only. For example, control with a scroll bar shouldn't be disabled or the user won't be able to scroll. Text boxes could be either (read-only allow the user to select and copy, disabled doesn't). Other controls could be disabled, if there's some way that the user can enable them (e.g. a save button that is only enabled once there are changes to save), or hidden if the user will only ever have a read-only view.
You'll most likely need a few ValueConverters to convert the boolean 'IsAdmin' (or whatever) flag to values that the WPF expects. For example you can bind IsEnabled directly, but IsReadOnly will be a converter to invert it. If you want to hide something, you'll need a converter like this:
public class BoolVisiblityInverseConverter: IValueConverter
{
/// <inheritdoc />
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value.GetType() != typeof(bool))
{
throw new ArgumentException("BoolVisiblityInverseConverter can only accept a bool");
}
var val = (bool)value;
return val ? Visibility.Collapsed : Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Then you'll need to define it in the Resources section of your XAML
<converters:BoolVisiblityInverseConverter x:Key="BoolVisiblityInverseConverter" />
and bind it to the Visibility property
<Button Visibility="{Binding IsAdmin, Converter={StaticResource BoolVisiblityInverseConverter}}" />
The goal with this method is that the interface between the View and ViewModel is as simple as possible. The VM can decide what mode to use, and the View displays every control in a suitable state.
You can easy do it with Visibility Converter. Place editable control and readonly control in same place.
Xaml:
<Window.Resources>
<myapp:BoolToVisible x:Key="bool2visible"/>
</Window.Resources>
<Grid Margin="10">
<StackPanel>
<CheckBox IsChecked="{Binding Mode}">Mode on</CheckBox>
<StackPanel Margin="10">
<TextBlock Text="{Binding Number}" Visibility="{Binding Mode, Converter={StaticResource bool2visible}, ConverterParameter=1}"/>
<TextBox Text="{Binding Number}" Visibility="{Binding Mode, Converter={StaticResource bool2visible}}"/>
</StackPanel>
</StackPanel>
</Grid>
Bool to visibility converter
public class BoolToVisible:IValueConverter
{
public BoolToVisible()
{
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var val=(bool)value;
if (parameter?.ToString() == "1")
{
val=!val;
}
if (val)
{
return Visibility.Visible;
}else
return Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
I have a big lists of objects which are binded to a ListBox. In that list box i am displaying the name of a file and a byte array of an image which is coming form WCF. I would display the files in the listbox depending on the scroll postion, so the file which are not visible from that scroll position to be set as Hidden.
I found on the internet a way which might help me but i cannot see a way that this will work.
I found convertors which should help me, and set up that class as a window resource. When I am opening the app all the items are converted to be visible.
This is the class:
class NullVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value == null ? Visibility.Hidden : Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value == null ? Visibility.Visible : Visibility.Hidden;
}
}
In Xaml i setup this class as a window Resource and i binded the functionality to the image and name in the Listbox items
<Window.Resources>
<view:NullVisibilityConverter x:Key="NullToVis"/>
</Window.Resources>
<Image Source="{Binding Path=Image}" Visibility="{Binding Path=Image, Converter={StaticResource NullToVis}}" Height="80" Width="80" Grid.Column="0"/>
<StackPanel Grid.Column="1" Visibility="{Binding Path=Image, Converter={StaticResource NullToVis}}" Orientation="Vertical" Width="80" Height="30">
<TextBlock Text="{Binding Path=Name}" Margin="5,1,0,1"/>
</StackPanel>
Does anyone have any idea how this might work?
So I have a ProgressRing and a TextBlock and I am trying to implement this basic hack, which is to display both elements when TextBlock's Text gets assigned a value (anything other than null), else both elements should hide when TextBlock's Text is null.
My Xaml looks like below. TextBlock's Text is binded to MessageForProgressRing and its Visibility is binded to both MessageForProgressRing and TargetNullValue. Same for me ProgressRing:
<StackPanel Panel.ZIndex="100" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center">
<mahControls:ProgressRing Height="50" IsActive="True" Width="50" Visibility="{Binding MessageForProgressRing, TargetNullValue=Collapsed, FallbackValue=Visible}" Foreground="White" Margin="0,0,0.2,0" />
<TextBlock Text="{Binding MessageForProgressRing}" Visibility="{Binding MessageForProgressRing, TargetNullValue=Collapsed, FallbackValue=Visible}"/>
</StackPanel>
Then, in code behind I just trigger the property and assign it a value on some button event handlers:
private void closeApplicationButtonTask()
{
((CaptureViewModel)DataContext).MessageForProgressRing = "Closing... ";
Application.Current.MainWindow.Close();
}
However, in my ViewModelBase (the parent of all my view models) it pops an error on OnPropertyChanged saying:
Requested value 'Closing...' was not found.
I think I need a converter because Visibility is binded to Closing... right? If yes how can I achieve it?
P.S I couldn't do it in OnPropertyChanged because I don't see the value to assign it. Also I don't think it is a good idea since it gets called big time before, during and after the execution.
I usually prefer to solve this problem by having a boolean property in my view model (e.g. HasMessageForProgressRing or IsProgressRingVisible). It's usually a more general-purpose solution. Then you can use a BooleanToVisibilityConverter.
If you truly want to implement a converter, just create a class that implements IValueConverter. The Convert implementation of this should be a piece of cake for your simple use case. ConvertBack isn't necessary in most cases (and won't be in yours). It would look something like this:
public class NullToCollapsed : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value != null ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
I'm building a wp7 app in Silverlight. I have some content that gets loaded asynchronously, and messages that indicate that loading is not yet done. I'd like to have the loading messages disappear as soon as the content's list box is not empty. Is it possible to do this just in XAML? Something like binding the Visibility property to StoryListBox.ItemsSource.IsEmpty?
StoryListBox is populated by having its ItemsSource set to an observable collection after the data is available.
<TextBox x:Name="LoadingMessage" Text="Loading..." Grid.Row="0" />
<ProgressBar x:Name="LoadingProgress" IsIndeterminate="True" Style="{StaticResource PerformanceProgressBar}" />
<ListBox x:Name="StoryListBox" Grid.Row="0" />
Update: I tried the following, but it doesn't work:
<StackPanel x:Name="Loading" Grid.Row="0" Visibility="{Binding StoryListBox.ItemsSource.IsEmpty, Converter={StaticResource visibilityConverter}}">
<TextBox Text="Loading..." />
<ProgressBar IsIndeterminate="True" Style="{StaticResource PerformanceProgressBar}" />
</StackPanel>
<ListBox x:Name="StoryListBox" Grid.Row="1" />
The Loading stack panel never collapses.
You seem to have answered your own question. Yes, you can simply bind the Visibility (or Busy/IsBusy on a BusyIndicator control to some attribute of another control).
If the specific property you want to bind to is not a bindable property, simply bind to the other control and customise the converter to get the member property you want. If you have specific code examples, just post them and I can post a more specific solution.
The usual problem is that the types (for visibility) are incompatible with boolean values, so you need to specifier a converter in the binding. Google for Silverlight VisibilityConvertor (they are a dime a dozen). Here is mine:
namespace Common.ValueConverters
{
using System;
using System.Windows;
using System.Windows.Data;
public class VisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is bool?)
{
if (string.IsNullOrEmpty((string)parameter))
{
return (value as bool?).Value ? Visibility.Visible : Visibility.Collapsed;
}
else
{
return (value as bool?).Value ? Visibility.Collapsed : Visibility.Visible;
}
}
throw new ArgumentException();
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
A use of the converter would look like:
<Grid Visibility="{Binding ShowDualView, Converter={StaticResource VisibilityConverter}}">
But quite frankly you are better of with a BusyIndicator control bound to an IsBusy property:
<Controls:BusyIndicator IsBusy="{Binding IsBusy}">
Just put it around the controls to you want to have hidden by the busy display.