Radiobutton wpf binding - wpf

I have a master-detail wpf application. The "master" is a datagrid , and "detail" is two radio buttons. Based on the row selection the radio buttons are checked in the "detail" section.
I am binding my Radio button the following way using a inttoboolean converter.
xaml :
<StackPanel Margin="2">
<RadioButton Margin="0,0,0,5" Content="In Detail" IsChecked="{Binding Path=itemselect.OutputType, Converter ={StaticResource radtointOTSB}, ConverterParameter= 0}"/>
<RadioButton Content="In Breif" IsChecked="{Binding Path=itemselect.OutputType, Converter ={StaticResource radtointOTSB}, ConverterParameter= 1}"/>
</StackPanel>
In the View Model:
public class radtointOTSB : IValueConverter
{
object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
int OTint = Convert.ToInt32(value);
if (OTint == int.Parse(parameter.ToString()))
return true;
else
return false;
}
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return parameter;
}
}
My implementation works well for the first few selections in datagrid. And all of a sudden , neither of my radio button is selected.
I have no clue on why it happens, any suggestion is welcomed.
Thanks in advance.

Search for problems with Binding multiple RadioButtons - there are enough complaints out there. Basically the binding won't receive the value of False because it not being passed to the Dependency Property..etc etc
Try using the following class instead of the regular RadioButton, bind to IsCheckedExt, as it forces the checkbox's IsChecked value to update.
public class RadioButtonExtended : RadioButton
{
public static readonly DependencyProperty IsCheckedExtProperty =
DependencyProperty.Register("IsCheckedExt", typeof(bool?), typeof(RadioButtonExtended),
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, IsCheckedRealChanged));
private static bool _isChanging;
public RadioButtonExtended ()
{
Checked += RadioButtonExtendedChecked;
Unchecked += RadioButtonExtendedUnchecked;
}
public bool? IsCheckedExt
{
get { return (bool?)GetValue(IsCheckedExtProperty); }
set { SetValue(IsCheckedExtProperty, value); }
}
public static void IsCheckedRealChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
_isChanging = true;
((RadioButtonExtended)d).IsChecked = (bool)e.NewValue;
_isChanging = false;
}
private void RadioButtonExtendedChecked(object sender, RoutedEventArgs e)
{
if (!_isChanging)
IsCheckedExt = true;
}
private void RadioButtonExtendedUnchecked(object sender, RoutedEventArgs e)
{
if (!_isChanging)
IsCheckedExt = false;
}
}

Related

How to determine whether MediaElement is playing?

I want to determine video is_playing on my player .
But how??
Please help me.
I am using c#>w_pf .net framework 4.5.1
I want to create a event like this video.
See Photo Demo
I want to control play/pause button like that player.
How can I control play/pause button image change while video is playing.
Please help me
i did this by having 2 buttons and binding the visibility of those buttons to a bool that you control when your buttons are clicked.
basically you must keep track of the play pause state yourself. media element wont do this for you.
in main window xaml add the following:
// Two converters used with the visibility binding
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<local:InvertableBooleanToVisibilityConverter x:Key="InvertableBooleanToVisibilityConverter"/>
</Window.Resources>
// Need to make sure we add loaded behaviour or it will crash app
<MediaElement Name="mePlayer"
LoadedBehavior="Manual"
Source="C:\Users\SamG\Downloads\ZW_20160102_064536A.avi"/>
<Button Content="Play" Name="Play" Click="Play_OnClick" Visibility="{Binding ElementName=mainWindow, Path=IsPaused, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<Button Content="Pause" Name="Pause" Click="Pause_OnClick" Visibility="{Binding ElementName=mainWindow, Path=IsPaused, Converter={StaticResource InvertableBooleanToVisibilityConverter}, ConverterParameter=Inverted}"/>
you must also name this window make sure you put this inside
x:Name="mainWindow"
in the c# code:
public partial class MainWindow : INotifyPropertyChanged
{
private bool _isPaused;
public MainWindow()
{
InitializeComponent();
mePlayer.Play();
IsPaused = true;
}
private void Play_OnClick(object sender, RoutedEventArgs e)
{
mePlayer.Play();
IsPaused = false;
}
private void Pause_OnClick(object sender, RoutedEventArgs e)
{
mePlayer.Pause();
IsPaused = true;
}
public bool IsPaused
{
get { return _isPaused; }
set
{
_isPaused = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
then add a new class called InvertableBooleanToVisibilityConverter:
[ValueConversion(typeof(bool), typeof(Visibility))]
public class InvertableBooleanToVisibilityConverter : IValueConverter
{
enum Parameters
{
Normal, Inverted
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var boolValue = (bool) value;
var direction = (Parameters) Enum.Parse(typeof (Parameters), (string) parameter);
if (direction == Parameters.Inverted)
return !boolValue ? Visibility.Visible : Visibility.Collapsed;
return boolValue ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
copy this code it should work for what you need

WPF | Expander Event

In my console I'm using two Expanders say(x & y)
by default it has been set 'IsExpanded = False'
once I click x then y should not be Expanded vice-versa
so please reply me with a code
Even if it is possible doing it in plain markup, it would probably better to use an attached behavior. Here an example:
class Toggle
{
Expander target;
public Toggle(Expander src,Expander target)
{
this.target = target;
src.Collapsed += new RoutedEventHandler(src_Collapsed);
src.Expanded += new RoutedEventHandler(src_Expanded);
}
void src_Expanded(object sender, RoutedEventArgs e)
{
target.IsExpanded = false;
}
void src_Collapsed(object sender, RoutedEventArgs e)
{
target.IsExpanded = true;
}
}
public static class ToggleExpanderBehavior
{
static List<Toggle> toggler = new List<Toggle>();
public static Expander GetTargetExpander(DependencyObject obj)
{
return (Expander)obj.GetValue(TargetExpanderProperty);
}
public static void SetTargetExpander(DependencyObject obj, string value)
{
obj.SetValue(TargetExpanderProperty, value);
}
// Using a DependencyProperty as the backing store for TargetName. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TargetExpanderProperty =
DependencyProperty.RegisterAttached("TargetExpander", typeof(Expander), typeof(ToggleExpanderBehavior), new UIPropertyMetadata(null,new PropertyChangedCallback(OnTargetChanged)));
static void OnTargetChanged(DependencyObject depo, DependencyPropertyChangedEventArgs depa)
{
if (depa.NewValue!=null)
{
if (depo is Expander)
{
var exp = depo as Expander;
toggler.Add(new Toggle(exp,depa.NewValue as Expander));
}
}
}
}
You van attach this behavior in xaml like this:
<Expander x:Name="X" IsExpanded="True" local:ToggleExpanderBehavior.TargetExpander="{Binding ElementName=Y}" >
<TextBlock>Content 1</TextBlock>
</Expander>
<Expander x:Name="Y" IsExpanded="False" local:ToggleExpanderBehavior.TargetExpander="{Binding ElementName=X}">
<TextBlock>Content 2</TextBlock>
</Expander>
</StackPanel>
and you have the toggle on.
This may help: Just register the expanded event for all your expander items (all the same event). If you open one, all others are closed:
private void expander_Expanded(object sender, RoutedEventArgs e)
{
SPExpander.Children.OfType<Expander>()
.All<Expander>(expander =>
{
if ((Expander)sender != expander)
expander.IsExpanded = false;
else
expander.IsExpanded = true;
return true;
});
}
Hope this solve you problem...
I would just Bind the IsExpanded property of one expander to the IsExpanded property on the other, then you just need to supply a value converter that inverts the value
public class BoolInverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var b = value as bool?;
return !b;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
var b = value as bool?;
return !b;
}
}

How do you set the target of a label so that the access key will focus on the control inside a ContentControl?

In WPF, how do you set the target of a label so that the access key will set focus on the control inside a ContentControl?
I am using MVVM and so I do not want to add any code to the code behind in order to solve this.
I have already tried setting the path to "Content" and at runtime an exception was thrown because there is no converter for the data type which is set to the content of the ContentControl. If I don't set the path, then focus is set to the ContentControl itself.
<Label Target="{Binding ElementName=_myContentControl, Path=Content}"/>
Use GotFocus event.
<Label Target="myContentControl" >_Content</Label>
<ContentControl x:Name="myContentControl" GotFocus="myContentControl_GotFocus">
 
private void myContentControl_GotFocus(object sender, RoutedEventArgs e)
{
var cc = sender as ContentControl;
if (cc != null && cc.Content is UIElement)
((UIElement)cc.Content).Focus();
}
Another solution using the separated class FocusBehavior:
class FocusBehaviour : Behavior<ContentControl>
{
protected override void OnAttached()
{
base.OnAttached();
this.AssociatedObject.GotFocus += new System.Windows.RoutedEventHandler(AssociatedObject_GotFocus);
}
void AssociatedObject_GotFocus(object sender, System.Windows.RoutedEventArgs e)
{
var c = this.AssociatedObject.Content as UIElement;
if (c != null)
c.Focus();
}
protected override void OnDetaching()
{
base.OnDetaching();
this.AssociatedObject.GotFocus -= new System.Windows.RoutedEventHandler(AssociatedObject_GotFocus);
}
}
XAML:
<ContentControl x:Name="myContentControl">
<i:Interaction.Behaviors>
<local:FocusBehaviour />
</i:Interaction.Behaviors>
</ContentControl>
This way requires a dll that is called System.Windows.Interactivity and is installed with Expression Blend SDK.
You could also use a converter to bind the label's Target to the Content of the ContentControl:
[ValueConversion(typeof(ContentControl), typeof(UIElement))]
public class ToContentConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var source = value as ContentControl;
if (source == null)
{
throw new ArgumentException("ToContentConverter source must be a ContentControl.");
}
return source.Content;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Declare the converter:
<Converters:ToContentConverter x:Key="ToContentConverter" />
And use it:
<Label Content="_Thing:" Target="{Binding ElementName=TheContentControl, Converter={StaticResource ToContentConverter}}" />
<ContentControl Name="TheContentControl" />
The approach I went with was similar to vorrtex's idea but doesn't require adding a reference to System.Windows.Interactivity
You create a boolean attached property with an event handler for when it changes. Add this property to your content control in the xaml. When the property is added, the event handler fires and here you can subscribe to the got focus event on your content control.
In the got focus event handler, you move focus to the next object which will be the content! Be sure that you set IsTabStop=False on the content control or you won't be able to Shift+Tab out of the content.
public static bool? GetFocusContent(DependencyObject obj)
{
return (bool?)obj.GetValue(FocusContentProperty);
}
public static void SetFocusContent(DependencyObject obj, bool? value)
{
obj.SetValue(FocusContentProperty, value);
}
public static readonly DependencyProperty FocusContentProperty =
DependencyProperty.RegisterAttached("FocusContent", typeof(bool?), typeof(MyClassName),
new UIPropertyMetadata(OnFocusContentChanged));
static void OnFocusContentChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
if (((bool?)e.NewValue).Value == true)
{
ContentControl cControl = obj as ContentControl;
if (cControl!= null)
{
cControl.GotFocus += OnGotFocus;
}
}
}
static void OnGotFocus(object sender, RoutedEventArgs e)
{
ContentControl cControl = sender as ContentControl;
// You should check the original source against the sender to make sure that
// you don't prevent focus from getting to a child of your content.
if (cControl != null && e.OriginalSource == sender)
{
cControl.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
}
}

Silverlight binding in a DataGridRowGroupHeader doesn't update when DataSource changes

I have a Binding in a inline style for the DataGridRowGroupHeader like this.
<sdk:DataGrid.RowGroupHeaderStyles>
<Style TargetType="sdk:DataGridRowGroupHeader">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="sdk:DataGridRowGroupHeader">
<TextBlock Margin="4,0,0,0" Text="{Binding Converter={StaticResource headerConverter}}" />
The DataGrid ItemsSource is Bound to a PageCollectionView containing an observable collection, which is grouped by a property in the collection. When I update the collection the rows of the grid change, but the binding in the GroupHeader does not change.
Is there a different way to bind this or a way to force the UI to update?
This is the converter I'm using on the Header binding:
public class GroupHeaderConverter2 : IValueConverter {
public object Convert(object value, System.Type targetType, object parameter, CultureInfo culture) {
var cvg = value as CollectionViewGroup;
return string.Format("({0} Remaining)", cvg.Items.Count((i) => ((CheckListEventDefinition)i).Complete == false && ((CheckListEventDefinition)i).Required == true));
}
public object ConvertBack(object value,
System.Type targetType,
object parameter,
CultureInfo culture) {
return null;
}
}
Got this to work by changing the source collection to my own extended ObservableCollection that also monitors the elements for PropertyChanged and then raises the CollectionChanged Event.
/// <summary> this collection is also monitoring the elements for changes so when PropertyChanged fires on any element, it will raise the CollectionChanged event</summary>
public class ObservableCollectionEx<T> : ObservableCollection<T> where T : INotifyPropertyChanged {
public ObservableCollectionEx(ObservableCollection<T> regularCollection) {
if (regularCollection != null) {
foreach (var item in regularCollection) {
this.Add(item);
}
}
}
public void RaiseCollectionChanged() {
this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) {
Unsubscribe(e.OldItems);
Subscribe(e.NewItems);
base.OnCollectionChanged(e);
}
protected override void ClearItems() {
foreach (T element in this)
element.PropertyChanged -= handlePropertyChanged;
base.ClearItems();
}
private void Subscribe(IList iList) {
if (iList == null) return;
foreach (T element in iList)
element.PropertyChanged += handlePropertyChanged;
}
private void Unsubscribe(IList iList) {
if (iList == null) return;
foreach (T element in iList)
element.PropertyChanged -= handlePropertyChanged;
}
private void handlePropertyChanged(object sender, PropertyChangedEventArgs e) {
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
The problem is you are binding directly to the object and not to a property with a Path. If you bind without a Path the binding will never update because there is no PropertyChanged event to notify the UI that the binding has changed. The simplest change is to change your binding to {Binding Items, Converter={StaticResource headerConverter}} and then cast value in your converter directly to ReadOnlyObservableCollection<object>.
If you need more flexibility then this I believe you will have to implement your own ICollectionView with a custom CollectionViewGroup.
Stephan
I follow your solution with a difference:
- i use a parameter
- i use a datagridcell
but when i modify my datasource the datagroupheader doesn't change.
<data:DataGridCell Content="{Binding Items,Converter={StaticResource myConverterBnc}, ConverterParameter=Fattura,UpdateSourceTrigger=PropertyChanged}" Foreground="White" Width="113"/>

Setting Visibility using MVVM pattern in silverlight

I take one grid in silverlight. Initially textbox2 is invisible. When I click on textbox1 we have to visible textbox2. I try it as belows:
<TextBox x:Name="textbox1" SelectionChanged="txt1_SelectionChanged"/>
<TextBox x:Name="textbox2 " Visibility="Collapsed"/>
private void txt1_SelectionChanged(object sender, RoutedEventArgs e)
{
textbox2 .Visibility = Visibility.Visible;
}
It works fine.
But I want to use MVVM pattern. So there I don't want to use eventHandler.
So how to do that using MVVM pattern?
edit: sorry, i thought you meant the textbox to be visible when the other one has focus, I changed my inital answer.
I can not try it at the moment, but you bind the Visibility property of your textbox to the SelectionLength property of the other, using a valueconverter:
<UserControl.Resources>
<local:IntToVisibilityConverter x:Key="IntToVisibilityConverter" />
</UserControl.Resources>
<Textbox
x:name="textbox2"
Visibility={Binding SelectionLength,
ElementName="textbox1"
Converter={StaticResource IntToVisibilityConverter}}
/>
implement the value converter like this:
public class IntToVisibilityConverter : IValueConverter
{
public Object Convert(Object value, Type targetType, Object parameter, CultureInfo culture)
{
return (int)value > 0 ? Visibility.Visible : Visibility.Hidden;
}
public Object ConvertBack(Object value, Type targetType, Object parameter, CultureInfo culture)
{
throw new InvalidOperationException("Converter cannot convert back.");
}
}
Create a property in viewmodel
public bool IsVisible
{
get
{
return _isVisible;
}
set
{
if (_isVisible == value)
{
return;
}
_isVisible = value;
RaisePropertyChanged("IsVisible");
}
}
This returns a boolean value so u need a converter BoolToVisibility Converter make BoolToVisibilityConverter class
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (parameter == null)
{
return ((bool)value == true) ? Visibility.Visible : Visibility.Collapsed;
}
else if (parameter.ToString() == "Inverse")
{
return ((bool)value == true) ? Visibility.Collapsed : Visibility.Visible;
}
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
Now Bind the TextBox and use the converter
<UserControl.Resources>
<local:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
</UserControl.Resources>
<Textbox x:name="textbox2" Visibility={Binding IsVisible,
Converter={StaticResource BoolToVisibilityConverter}}/>
This is it.
The biggest problem you will have is getting the SelectionChanged event sent to the ViewModel. Commands in SL4 only work on button clicks, so TextBox SelectionChanged events can't fire commands by default.
There are a few solutions out there for you:
Binding Commands to ANY event
EventToCommand Behavior
Once you have done that, you can have a command in your ViewModel that sets a Visibility property in your ViewModel and fires the PropertyChanged event.
Using my ViewModelSupport library, the VM would look like this:
public class MyViewModel : ViewModelBase
{
public Visibility ShowTextbox2
{
get { return Get(() => ShowTextbox2, Visibility.Collapsed); }
set { Set(() => ShowTextbox2, value); }
}
public void Execute_SelectionChanged()
{
ShowTextbox2 = Visibility.Visible;
}
}
}
You would then bind the SelectionChanged event to the SelectionChanged command in the VM and the Textbox2 visibility attribute to the ShowTextbox2 property in the VM.
Good luck.
If you are using MVVM Light, you can also do it like this:
using System.Windows; //place it at the top of your view model class.
private Visibility _isVisible = Visibility.Collapsed;
public Visibility IsVisible
{
get
{ return _isVisible; }
set
{
if (_isVisible == value) { return; }
RaisePropertyChanging(() => IsVisible);
_passwordMissing = value;
RaisePropertyChanged(() => IsVisible);
}
}

Resources