Binding Buttons' style to ViewModel property in WP7 - c#

I have a play button in a AudioRecord View.
Currently it is declered as:
<Button Width="72" Height="72" Style="{StaticResource RoundPlay}"
DataContext="{Binding ElementName=this, Path=DataContext}"
cmd:ButtonBaseExtensions.Command="{Binding PlayStopCommand}"
/>
When a user clicks the button, a PlayStopCommand in items ViewModel gets executed. I want the button to get its' style set to "RoundStop" whenever the sound is playing.
How can I bind the buttons' Style to a property in my ViewModel (what property type should I use), so that the look of the button is controllable from code?
I have RoundStop style defined, I just need a way to apply it to a button from code.

You should define the playing state in you viewmodel (Playing/Stopped), and bind Button.Style to that property using a converter. In your converter, return a different style (taken from App.Current.Resources) based on the current state.
Edit:
Here's an example of your converter should look like:
public class StateStyleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return (PlaybackState)value == PlaybackState.Playing ? App.Current.Resources["RoundPlay"] : App.Current.Resources["RoundStop"];
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
In this example, PlaybackState is an enum:
public enum PlaybackState
{
Playing,
Stopped
}
Then you should add the state property to your view model (The part where you notify the change depends on the framework you are using for MVVM):
private PlaybackState state;
public PlaybackState State
{
get { return state; }
set
{
state = value;
RaiseNotifyPropertyChanged("State");
}
}
Declare your converter in XAML:
<UserControl.Resources>
<converters:StateStyleConverter x:Key="StateStyleConverter"/>
</UserControl.Resources>
And finally bind it to the button:
<Button Width="72" Height="72" Style="{Binding State, Converter={StaticResource StateStyleConverter}}"
DataContext="{Binding ElementName=this, Path=DataContext}"
cmd:ButtonBaseExtensions.Command="{Binding PlayStopCommand}"
/>

You could use a ToggleButton and make the necessary visual changes in the visual states for checked/unchecked.
If you must do it the way your question states, then you can define the Style in the resources and then access it in the code-behind from this.Resources["YourStyleKey"]; Your problem will be getting it from the view to the view model, hence my first suggestion :)

Related

Combox not updating with binding

Everytime i change my selected item inside my UI it's not updating my combobox.
XAML
<ComboBox x:Name="CompanyComboBox" HorizontalAlignment="Left" Height="26"
Margin="100,41,0,0" VerticalAlignment="Top" Width="144"
SelectionChanged="CompanyComboBox_SelectionChanged"
SelectedItem="{Binding SelectedCompany, UpdateSourceTrigger=PropertyChanged, Mode=OneWayToSource}">
<ComboBox.ItemTemplate>
<DataTemplate>
<ContentPresenter
Content="{Binding Converter={StaticResource DescriptionConverter}}">
</ContentPresenter>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
C#
private Company _selectedCompany;
public Company SelectedCompany
{
get { return _selectedCompany; }
set
{
if (value == _selectedCompany)
return;
_selectedCompany = value;
OnPropertyChanged(nameof(SelectedCompany));
}
}
Just to clarify the Company class is actually an ENUM
DescriptionConverter:
public class CompanyDescriptionConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var type = typeof(Company);
var name = Enum.GetName(type, value);
FieldInfo fi = type.GetField(name);
var descriptionAttrib = (DescriptionAttribute)
Attribute.GetCustomAttribute(fi, typeof(DescriptionAttribute));
return descriptionAttrib.Description;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
what i mean by inside my UI, is i have a list of companies set to a combobox item source, and when i change the combobox value to another company, it doesn't update in my source, it stay's as default.
My Enum might clarify the problem for someone:
[Description("Netpoint Solutions")]
Company1 = 0,
[Description("Blackhall Engineering")]
Company2 = 180,
Try to remove Mode=OneWayToSource and your event handler:
SelectionChanged="CompanyComboBox_SelectionChanged"
You don't need to handle the SelectionChanged event when you bind the SelectedItem property.
Also make sure that you set the DataContext to an instance of your class where the SelectedCompany property is defined.
Your Binding is defined as OneWayToSource. When you want it to be updated from the viewModel, you should set it to TwoWay.
See the documentation of Bindings for more details: https://msdn.microsoft.com/de-de/library/ms752347(v=vs.110).aspx
EDIT:
I skipped the part where you have an Enum as the source. I do not see, that you define the ItemsSource for the Combobox, where is this done? The value passed to the setter of SelectedCompany has to be in the Collection defined as ItemsSource.
For Enums, you can refer to this thread: How to bind an enum to a combobox control in WPF?

How Can I change listbox's textboxes apearance depending on object that goes there?

Im new here, I have built this small uwp app using binded ObservableCollection to a Listbox, I wanted to know how to change apearence of Textbox inside listbox. To be precise I have ObservableCollection which is made out of objects and one property of this object is a boolean. "UsersWithIndications.CheckedInOrOut" = boolean. I want to make it so if this boolean is true, textbox of this single User becomes green, if its false = red... Can You please show me a direction of resolving this issue? How can I access each individual textbox in this Listbox? If any more code is required, please let me know!
Xaml code for the page
App Launched, Listbox
Method 1:
Using Converter
Here is the code for Converter
public class MyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if ((string)value == "true")
return new SolidColorBrush(Colors.Green);
else
return new SolidColorBrush(Colors.Red);
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
Here is the code Data Binding
<Page.Resources>
<local:MyConverter x:Key="MyConverter"/>
</Page.Resources>
<TextBlock Name="MyOutput" Text="true" Foreground="{Binding Path=Text, Converter={StaticResource MyConverter}, ElementName=MyOutput}"/>
Method 2:
Using separate property for Foreground color

Inverted bool to radio button from dataContext to userControl

How can I bind an inverted value of a bool in my xaml?
I know, I know, there are a lot of q&a about this, but there aren't any about a specific case: when the converter is in a view model and the radio button in a user control.
how can I correctly refer to the main window view model data context? In other case I used the code I've posted, but in this case I don't get how to use it.
UPDATE CODE:
namespace ***.ViewModel
{
[ValueConversion(typeof(bool), typeof(bool))]
public class InverseBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
if (targetType != typeof(bool))
throw new InvalidOperationException("The target must be a boolean");
return !(bool)value;
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
}
class MainWindowViewModel : MyClass.UtilityClasses.ViewModelBase
{
public MainWindowViewModel(){
SaveCommand = new DelegateCommand(SaveData, CanSave );
UndoCommand = new DelegateCommand(UndoActions, CanSave);
[...]
}
....
}
ANOTHER CODE UPDATE:
In my xaml, I have a devexpress GridControl where I list my observableCollection from db. When I click one element, a layout group is populated with the relative data.
In this layout group, I have:
<StackPanel Margin="0" Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Left">
<RadioButton Content="{DynamicResource Locale}" Margin="10,0,0,0" x:Name="rd_LOCALE" VerticalAlignment="Center" IsChecked="{Binding Path=REMOTO, Converter={StaticResource InverseBooleanConverter}}" GroupName="Location" Panel.ZIndex="9" TabIndex="10" />
<RadioButton Content="{DynamicResource Remoto}" Margin="10,0,6,0" x:Name="rd_REMOTO" VerticalAlignment="Center" IsChecked="{Binding REMOTO}" GroupName="Location" Panel.ZIndex="10" TabIndex="11" Tag="PRISMA" />
</StackPanel>
WhenI change from one record to another, the converter gives me error... why? It fails the "if (targetType != typeof(bool))" row. So I tried to change that like:
if (value.getType() != typeof(bool))
but in this way, without fails nothing in the code, it put the wrong value in the radiobutton!
You need to make sure that the value converter is referenced in the XAML
<UserControl.Resources>
<myproject:InverseBooleanConverter x:Key="InverseBooleanConverter" />
</UserControl.Resources>
where my project is the namespace in which the value converter class is defined

How to change the visible property of the text box from the view model ( WPF, MVVM)

I am a beginner here in WPF and MVVM. I have certain controls on a window in my project. For example, I have a text box in my window. I am using MVVM Pattern and here I want to change the visible property of the text box from the view model.
One other thing is that, I want to change the visibility of the text box from the viewmodel based on some conditions.
Well, I googled it and google throws me some suggestions which were all different solutions and I'm in a total confusion.
Guess some one can help me figure this out.
I know this would be a piece of cake for the WPF MVVM Experts, but since I am trying to learn this stuff I require some code as examples.
Thanks
Since this is MVVM, you don't want to change the visibility of the textbox you actually want to disable some option.. Then - whether that option is enabled or disabled should reflect on the visibility of your Textbox.
So basically you want a Property in the ViewModel such as:
public bool CanMyPropertyBeChanged {get; set;}
Which you can change (of course you should probably implement INotifyPropertyChanged if you haven't already)...
And bind the visibility of the Textbox to this property, via a Converter:
<TextBox Visibility="{Binding CanMyPropertyBeChanged, Converter={StaticResource boolToVis}}" />
You can use the built-in BooleanToVisibilityConverter for this:
<BooleanToVisibilityConverter x:Key="boolToVis" />
In you XAML file add the following:
<Window.Resources>
<ResourceDictionary>
<BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter" />
</ResourceDictionary>
<Window.Resources>
On your textbox add:
<TextBox .... Visibility="{Binding IsVisibleBoolean, Converter={StaticResourcebooleanToVisibilityConverter}}" />
In your viewmodel add the IsVisibleBoolean property:
public bool IsVisibleBoolean
{
get; set;
}
you can do it multiple way
first of all you could bind it directly
XAML
<TextBox Visibility="{Binding myVisibility}"/>
VM Property
public Visibility myVisibility
{
get { return Visibility.Hidden; }
}
but you could also use a Converter (the recommended way)
XAML
xmlns:local="clr-namespace:yourNamespace">
<Window.Resources>
<local:BooleanToVisibilityConverter x:Key="BooleanToVisibility" />
</Window.Resources>
<TextBox Visibility="{Binding myVisibility,Converter={StaticResource BooleanToVisibility}}"/>
VM Property
public bool myVisibility
{
get { return false; }
}
BooleanToVisibilityConverter.cs
[ValueConversion(typeof(bool),typeof(Visibility))]
public sealed class BooleanToVisibilityConverter : IValueConverter
{
public bool IsReversed { get; set; }
public bool UseHidden { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var val = System.Convert.ToBoolean(value, CultureInfo.InvariantCulture);
if (this.IsReversed)
{
val = !val;
}
if (val)
{
return Visibility.Visible;
}
return this.UseHidden ? Visibility.Hidden : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

Binding with ValueConverter to object in another window

I have a main program window with a row of shortcut buttons along the bottom. I'm trying to make the Visibility of these selectable through a separate Settings window using CheckBoxes, and then store that state in the UserSettings of the program so when it's opened again the previous setting will be remembered. I've found and used an IValueConverter to implement this, and I know the Setting is saved as the CheckBox itself retains it's value.
The problem is that clicking the CheckBox does not affect the Visibility of the button. It works within the Settings window itself, but I can't seem to figure out how to make it work between different windows.
I have tried implementing both the UpdateSourceTrigger & NotifyOnSourceUpdated flags to no avail. Can anybody see the problem?
Main Window XAML
<WrapPanel.Resources>
<main:BooleanToHiddenVisibility x:Key="boolToVis" />
</WrapPanel.Resources>
<ToggleButton Name="alwaysOnTop" Checked="alwaysOnTop_Checked"
Style="{StaticResource ShortcutToggleStyle}" Unchecked="alwaysOnTop_Unchecked"
Visibility="{Binding Source=main:Properties.Settings.Default, Path=pinShow, Converter={StaticResource boolToVis}, Mode=TwoWay}" >
<Image SnapsToDevicePixels="True" Source="Images/pushpin.png"
ToolTip="Always on Top" />
</ToggleButton>
Settings Window XAML
<CheckBox Name="pinDisable" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Center"
IsChecked="{Binding Source={x:Static main:Properties.Settings.Default}, Path=pinShow, Mode=TwoWay}"
Checked="pinDisable_Checked" Unchecked="pinDisable_Unchecked"/>
Convertere Code-Behind
public class BooleanToHiddenVisibility : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Visibility rv = Visibility.Visible;
try
{
var x = bool.Parse(value.ToString());
if (x)
{
rv = Visibility.Visible;
}
else
{
rv = Visibility.Collapsed;
}
}
catch (Exception)
{
}
return rv;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value;
}
}

Categories