WPF buttons not binding to view model - c#

I have an WPF application with 8 buttons. Four of which work fine. I then added another 4 buttons. These button do not bind to my view model for some reason. When I click on the buttons nothing is called in my view model. Everything appears the same as the four working buttons to me and for the life of me I can't see why these new buttons do not bind to my view model?
View Model
public ICommand CommandButtAppendComments { get; set; }
private bool _appendbuttVisibleComments;
public bool AppendButtVisibleComents
{
get { return _appendbuttVisibleComments; }
set
{
_appendbuttVisibleComments = value;
OnPropertyChanged("AppendButtVisibleComents");
}
}
public ViewModel()
{
CommandButtAppendComments = new MyCommands(ExecuteCommandButtAppendComments, CanExecuteCommandButtAppendComments);
}
#region Append Comments Button
private bool CanExecuteCommandButtAppendComments(object parameter)
{
return true;
}
private void ExecuteCommandButtAppendComments(object parameter)
{
AppendButtVisibleComents = false;
DetachButtVisibleComents = true;
}
#endregion
XAML
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
</Window.Resources>
<Button Grid.Row="0" Grid.Column="5" Height="30" Width="60" Content="Append" Command="{Binding CommandButtAppendComments}" Style="{StaticResource ButtonTemplate}" Visibility="{Binding AppendButtVisibleComents, Converter={StaticResource BoolToVis}}"/>

Related

How to bind a visibility of HamburgerButtonInfo to another viewmodel other than ShellViewModel?

Question
How can I change the visibility of my hamburger button by not using shellviewmodel ?
P.s. : Its an UWP app working on template10.
Is it possible to bind the Hamburger button visibility to two different Viewmodels in template10?
Shell.xaml
xmlns:vm="using:ScanWorx.ViewModels"
xmlns:converters="using:ScanWorx.ViewModels"
<Page.DataContext>
<vm:ShellViewModel x:Name="ViewModel" />
</Page.DataContext>
<Page.Resources>
<converters:BooleanToVisibilityConverter x:Key="Converter" />
</Page.Resources>
<controls:HamburgerMenu x:Name="MyHamburgerMenu">
<controls:HamburgerMenu.PrimaryButtons>
<!-- HeatMap Generator Button -->
<controls:HamburgerButtonInfo ClearHistory="True" PageType="views:HeatMapGeneratorPage"
Visibility="{x:Bind vm:LoginPageViewModel.abc, Mode=TwoWay,
Converter={StaticResource Converter}}">
<StackPanel Orientation="Horizontal">
<SymbolIcon
Width="48"
Height="48"
Symbol="ViewAll" />
<TextBlock
Margin="12,0,0,0"
VerticalAlignment="Center"
Text="HeatMap Generator" />
</StackPanel>
</controls:HamburgerButtonInfo>
</controls:HamburgerMenu.PrimaryButtons>
</controls:HamburgerMenu>
LoginPageViewModel.cs
namespace ScanWorx.ViewModels
{
class LoginPageViewModel : ViewModelBase
{
public static bool abc { get; set; }
public static Visibility visibility1 { get; set; }
public async void Button_Login_Click()
{
try
{
*code to decrypt my login details and then after decryptng i check for next condition*
if (ApplicationData.Current.LocalSettings.Values["UserAccessLevel"].ToString() == "Administrator")
{
abc = true;
visibility1 = Visibility.Visible;
}
else
{
abc = false;
visibility1 = Visibility.Collapsed;
}
}
}
}
}
ShellViewModel.cs :
If i use shellviewModel in binding The hiding works fine by changing - Visibility="{x:Bind vm:ShellViewModel.ShowButton} , but with this it can only be hard coded either false or true making it visible or collapsed once when app starts.
But i dont want to change the visibility of my button with shell view model i want to change it after i log in with the LoginPageViewModel*
namespace ScanWorx.ViewModels
{
class ShellViewModel : ViewModelBase
{
public static bool ShowButton { get; set; }
public ShellViewModel()
{
ShowButton = false;
}
}
}
How to bind a visibility of HamburgerButtonInfo to another viewmodel other than ShellViewModel?
The better way is make a global setting class to record if login. After login success, edit the setting class ShowButton bool property to true.
Setting.cs
public class Setting : INotifyPropertyChanged
{
private bool _showBtn = false;
public bool ShowBtn
{
get { return _showBtn; }
set { _showBtn = value; OnPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Xaml bind
<Application.Resources>
<ResourceDictionary>
<local:Setting x:Key="Setting"/>
</ResourceDictionary>
</Application.Resources>
......
Visibility="{Binding ShowBtn, Source={StaticResource Setting}}"
Value Change
((Setting)Application.Current.Resources["Setting"]).ShowBtn = true;

C# UWP binding splitview IsPaneOpen to viewmodel

I was learning on some stuff on universal windows app when i came across this problem:
i want to build a splitview menu with a hamburger button without code behind.
so i setup a viewmodel with a property and a command for changing the value of that property. to check if the commmand is fired i included a small messagedialog.
i bound the splitview IsPaneOpen to my viewmodel but somehow it does not seem to work.
xaml code
<Page.Resources>
<vm:PaneViewModel x:Key="viewModel"/>
</Page.Resources>
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" DataContext="{StaticResource viewModel}" >
<Button Content="Test" Command="{Binding Path=OpenPane, Mode=TwoWay}" ManipulationMode="All"/>
<SplitView DisplayMode="CompactInline"
x:Name="Splitview"
OpenPaneLength="150"
CompactPaneLength="20"
IsPaneOpen="{Binding IsPaneOpen, Mode=TwoWay}">
<SplitView.Pane>
<StackPanel Height="400">
<Button Height="40">
<TextBlock Text="Testbutton" Width="100"/>
</Button>
</StackPanel>
</SplitView.Pane>
<SplitView.Content>
<TextBlock Margin="30" Text="{Binding ShowAnything, Mode=TwoWay}"/>
</SplitView.Content>
</SplitView>
</StackPanel>
ViewModel Code
internal class PaneViewModel
{
public PaneViewModel()
{
OpenPane = new OpenPaneCommand(this);
}
private bool isPaneOpen = true;
public bool IsPaneOpen
{
get
{
return isPaneOpen;
}
set
{
isPaneOpen = value;
}
}
public string ShowAnything { get { return isPaneOpen.ToString(); } }
public OpenPaneCommand OpenPane { get; set; }
public void OpenPaneMethod()
{
if (isPaneOpen == false)
isPaneOpen = true;
else
isPaneOpen = false;
}
}
and Command Code
internal class OpenPaneCommand : ICommand
{
public OpenPaneCommand(PaneViewModel ViewModel)
{
this.viewModel = ViewModel;
}
private PaneViewModel viewModel;
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
Blub();
viewModel.OpenPaneMethod();
}
async private void Blub()
{
var dialog = new MessageDialog("Testausgabe");
await dialog.ShowAsync();
}
like i said - the messagedialog shows up, but neither the textblock in the splitview.content or ispaneopen seems to change. debuging shows me that my method to change the value does indeed change the value.
so i was wondering if my binding or datacontext-setting was off.
Maybe you guys got an hint for me where my missunderstanding comes from.
thanks!
meq
Your binding isn't working because the View isn't notified of change on your ViewModel. Your VM needs to implement INotifyPropertyChanged interface and raise the PropertyChanged event whenever your property changes.
So typically you would put something like this to your setter:
...
set
{
isPaneOpen = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsPaneOpen");
}
...
I think your view model should inherit the ObservableObject.
and further all properties should be update like below:
public bool IsPaneOpen
{
get { return isPaneOpen; }
set
{
this.Set<bool>(ref this._loisPaneOpendedPendingCount, value);
}
}
same for ShowAnything property

ListView strange behavoiur with blend trigger

I have simple ListView with trigger also I am using mvvm light RelayCommand.
The main question is why when function ChangeShowingMode(ObservableCollection<Employee> items) fires in console it displays only Firing: 0. Why it do not show also Firing: 1,Firing: 5,Firing: 11,Firing: 99. How to make it?
xmlns:i="http://schemas.microsoft.com/expression/2010/interactions"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactivity"
<Grid>
<ListView ItemsSource="{Binding Items}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<CheckBox IsChecked="{Binding IsChecked}" VerticalAlignment="Center">
<ei:Interaction.Triggers>
<ei:EventTrigger EventName="Checked">
<ei:InvokeCommandAction Command="{Binding DataContext.IsCheckedTrueCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Views:MainWindow}}}" CommandParameter="{Binding .}"/>
</ei:EventTrigger>
</ei:Interaction.Triggers>
</CheckBox>
<Label Grid.Column="1" Content="{Binding Name}" VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
Code Looks like:
namespace WpfApplication
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ListViewModel();
}
}
public class Employee : ViewModelBase
{
private bool isChecked;
public bool IsChecked
{
get
{
return this.isChecked;
}
set
{
this.isChecked = value;
this.RaisePropertyChanged("IsChecked");
}
}
public string Name { get; set; }
}
public class ListViewModel : ViewModelBase
{
private ObservableCollection<Employee> items;
public ObservableCollection<Employee> Items
{
get
{
return this.items;
}
set
{
this.items = value;
this.RaisePropertyChanged("Items");
}
}
public ListViewModel()
{
Items = new ObservableCollection<Employee>();
LoadAsync();
}
public void LoadAsync()
{
Task t = null;
t = Task.Factory.StartNew(new Action(() =>
{
System.Threading.Thread.Sleep(5000);
ObservableCollection<Employee> temporaryItems = new ObservableCollection<Employee>();
for (int i = 0; i < 100; i++)
{
temporaryItems.Add(new Employee { IsChecked = false, Name = i.ToString() });
}
Items = temporaryItems;
}));
t.ContinueWith((key) => { ChangeShowingMode(Items); });
}
public void ChangeShowingMode(ObservableCollection<Employee> items)
{
Items[0].IsChecked = true;
Items[1].IsChecked = true;
Items[5].IsChecked = true;
Items[11].IsChecked = true;
Items[99].IsChecked = true;
}
public RelayCommand<Employee> IsCheckedTrueCommand
{
get
{
return new RelayCommand<Employee>((emp) => Command(emp));
}
}
public void Command(Employee emp)
{
Console.WriteLine("Firing: {0}", emp.Name);
}
}
}
The Checked Event will raise only for visible Checkboxes. So the command is only called for the visible ones.
By test your provided example, the Properties are set by the task and also reflected as expected by the UI. But the Command is only called, when I manually check a checkbox, not through initialisation.
Changing
t.ContinueWith((key) => { ChangeShowingMode(Items); });
to
t.ContinueWith((key) => { Syste.Threading.Thread.Sleep(5000); ChangeShowingMode(Items); });
has the result, that the Command is called for the visible Checkboxes.
If you scoll down when the checkboxes are displayed, the command is called for Checkbox 99.
But this behavior isn't strange at all. I think, it is a timming-Issue when your viewmodel is connected to the Datacontext or not.
The answer to your question "How to make it?" depends on what is your problem with the current solution.
To watch the property changes, you could
How to Listen to Property Changes of Items of an ObservableCollection
and call a command on changes.
But I think you don't need this at all. The checked-State is reflected by your IsChecked-Property through the Two-Way binding.
<CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}" VerticalAlignment="Center">
So you can easily get them by
var checkedItemsList = Items.Where(ele => ele.IsChecked).ToList();
And if you make Changes by Code, you can call the Command manually in your viewmodel.
Items[0].IsChecked = true;
if (IsCheckedTrueCommand.CanExecute(Items[0]))
IsCheckedTrueCommand.Execute(Items[0]);
But I'm not sure if I get you here. The question remains what the command should do in an enhanced scenario.
Btw, which Version of Framework you are using? See check box binding not working on .NET 3.5 SP1
And to call a Comand on User-Interaction you can use:
<CheckBox CommandParameter="{Binding}"
Command="{Binding DataContext.CheckBoxCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"
IsChecked="{Binding IsChecked, Mode=TwoWay}" VerticalAlignment="Center">

setting the DataContex correctly

im building a UserControl MyUserControl that has his own ViewModel MyUserControlViewModel. MyUserControl contains 6 VehicleSelectionBlock (V1, ... V6). VehicleSelectionBlock is a UserControl i've made. it has 3 RadioButton: car, train, bus; all are of enum type Vehicle and of the same GroupName VehicleGroup.
my goal is to represent each of MyUserControl's VehicleSelectionBlocks in MyUserControlViewModel.
to make my self clear: in MyUserControlViewModel i want to be able to know&change what RadioButton is checked in every one of the 6 VehicleSelectionBlock. i think my main problem is not the converter but rather the DataContex - i'm not sure how to set it correctly for each of the controllers.
iv'e tried Binding (which is the obvious solution). i tried reading here, here , and here. unfortunately neither one helped my acheive my goal.
my code is below - im kinda new to wpf and data binding in generally. i've read almost every chapter in this tutorial but still lost sometimes.
please help me get through this and understand better the DataContex concept.
ty
MyUserContlor.xaml.cs:
namespace Project01
{
/// <summary>
/// Interaction logic for MyUserContlor.xaml
/// </summary>
public partial class MyUserContlor : UserControl
{
public MyUserContlorViewModel ViewModel { get; set; }
public MyUserContlor()
{
ViewModel = new MyUserContlorViewModel();
InitializeComponent();
this.DataContext = ViewModel;
}
private void BtnImReady_OnClick(object sender, RoutedEventArgs e)
{
//this code is irrelevant to the question
throw NotImplementedException();
}
}
}
MyUserContlor.xaml:
<UserControl x:Class="Project01.MyUserContlor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:loc="clr-namespace:Project01"
mc:Ignorable="d"
HorizontalContentAlignment="Center" VerticalContentAlignment="Center">
<Viewbox Stretch="Uniform">
<StackPanel>
<loc:VehicleSelectionBlock Name="V1"/>
<loc:VehicleSelectionBlock Name="V2"/>
<loc:VehicleSelectionBlock Name="V3"/>
<loc:VehicleSelectionBlock Name="V4"/>
<loc:VehicleSelectionBlock Name="V5"/>
<loc:VehicleSelectionBlock Name="V6"/>
<Button x:Name="BtnImReady" Click="BtnImReady_OnClick">Im Ready!</Button>
</StackPanel>
</Viewbox>
</UserControl>
MyUserContlorViewModel.cs:
namespace Project01
{
public class MyUserContlorViewModel : INotifyPropertyChanged
{
public MyUserContlorViewModel()
{
VehicleArr = new MyViewModel_Vehicle[6];
PropertyChanged+=MyUserControlViewModel_PropertyChanged;
}
public MyViewModel_Vehicle[] VehicleArr;
public event PropertyChangedEventHandler PropertyChanged;
public PropertyChangedEventHandler GetPropertyChangedEventHandler() { return PropertyChanged; }
private void MyUserControlViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
//might be useful
throw NotImplementedException();
}
}
//this class should represent a VehicleSelectionBlock
public class MyViewModel_Vehicle
{
public Vehicle VehicleSelected {get; set;}
MyViewModel_Vehicle(){}
MyViewModel_Vehicle(Vehicle v){ VehicleSelected = v;}
}
}
VehicleSelectionBlock.xaml:
<UserControl x:Class="Project01.VehicleSelectionBlock"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Project01"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}">
<Border VerticalAlignment="Center" HorizontalAlignment="Center" Background="GhostWhite"
BorderBrush="Gainsboro" BorderThickness="1">
<StackPanel >
<Label Content="{Binding Name}"
FontWeight="Bold" HorizontalContentAlignment="Center"></Label>
<RadioButton GroupName="VehicleGroup" >car</RadioButton>
<RadioButton GroupName="VehicleGroup">train</RadioButton>
<RadioButton GroupName="VehicleGroup" IsChecked="True">bus</RadioButton>
</StackPanel>
</Border>
</Grid>
</UserControl>
VehicleSelectionBlock.xaml.cs:
namespace Project01
{
/// <summary>
/// Interaction logic for VehicleSelectionBlock.xaml
/// </summary>
public partial class VehicleSelectionBlock : UserControl
{
public VehicleSelectionBlock()
{
InitializeComponent();
}
public VehicleSelectionBlock(String name)
{
name = Name;
InitializeComponent();
}
public static readonly DependencyProperty NameProperty = DependencyProperty.Register(
"Name", typeof (String), typeof (VehicleSelectionBlock), new PropertyMetadata(default(String)));
public String Name
{
get { return (String) GetValue(NameProperty); }
set { SetValue(NameProperty, value); }
}
}
public enum Vehicle { Car, Train, Bus}
}
here is a quick solution. keep in mind that the code needs to change if you want to add more values to your Vehicle enum.
the MyUserControlViewModel.cs file
public class MyUserControlViewModel
{
public MyUserControlViewModel()
{
VehicleArr = new VehicleViewModel[6];
for (int i = 0; i < 6;i++ )
VehicleArr[i] = new VehicleViewModel();
}
public VehicleViewModel[] VehicleArr { get; set; }
}
this will expose your 6 items. They could be more. As a result they will be displayed in an ItemsControl, as you will see later.
public class VehicleViewModel:ViewModelBase
{
private bool isCar, isTrain, isBus;
public bool IsCar
{
get { return isCar; }
set
{
if (isCar == value) return;
isCar = value;
OnChanged("IsCar");
}
}
public bool IsTrain
{
get { return isTrain; }
set
{
if (isTrain == value) return;
isTrain = value;
OnChanged("IsTrain");
}
}
public bool IsBus
{
get { return isBus; }
set
{
if (isBus == value) return;
isBus = value;
OnChanged("IsBus");
}
}
}
instances of VehicleViewModel will contain your radio selection using 3 bool properties. this is the solution disadvantage. If you want more values you'll have to add more properties. you can see this inherits ViewModelBase. ViewModelBase just implements INPC so i'm not going to put it here. ViewModelBase also exposes the OnChange method that triggers the INPC event.
displaying the list can be done in your MyUserControl by using an ItemsControl like below.
<ItemsControl ItemsSource="{Binding VehicleArr}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<loc:VehicleControl />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
each item is also a UserControl. The VehicleControl user control is just a StackPanel that displays the RadioButons. This can be seen below.
<StackPanel Orientation="Horizontal">
<RadioButton Content="Car" Margin="5" VerticalAlignment="Center" IsChecked="{Binding Path=IsCar, Mode=TwoWay}"/>
<RadioButton Content="Train" Margin="5" VerticalAlignment="Center" IsChecked="{Binding Path=IsTrain, Mode=TwoWay}"/>
<RadioButton Content="Bus" Margin="5" VerticalAlignment="Center" IsChecked="{Binding Path=IsBus, Mode=TwoWay}"/>
</StackPanel>
please notice that each RadioButton is bound to one of the 3 properties in the VehicleViewModel instance.
Once you press your button you should have all the selections recorded. if you want you could have a function that returns an enum value by analysing the 3 bool properties if that is what you need.
the best solution will be to get rid of the radio buttons and replace them with combo boxes. in this way you can change the enum members and everything will continue to work without changing anything else. this might look as below.
public class VehicleViewModel:ViewModelBase
{
private Vehicle selOption;
private readonly Vehicle[] options;
public VehicleViewModel()
{
this.options = (Vehicle[])Enum.GetValues(typeof(Vehicle));
}
public Vehicle[] Options { get { return options; } }
public Vehicle SelectedOption
{
get { return selOption; }
set
{
if (selOption == value) return;
selOption = value;
OnChanged("SelectedOption");
}
}
}
and for the view:
<ItemsControl ItemsSource="{Binding VehicleArr}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Options}"
SelectedItem="{Binding SelectedOption, Mode=TwoWay}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
You can do directly in the code-behind of your control (in the default constructor)
public VehicleSelectionBlock()
{
InitializeComponent();
this.DataContext = new MyUserContlorViewModel ();
}
You can also do that in XAML (http://msdn.microsoft.com/en-us/library/ms746695(v=vs.110).aspx) declaration, as you wish.

Enable,Disable button upon check/uncheck of checkboxes

I have a view that contains a list box with various items in button form and a checkbox for each of the button. XAML:
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<CheckBox x:Name="CheckFavorite"
Width="Auto"
Height="Auto"
AutomationProperties.AutomationId="AID_FavoritesCheck"
IsChecked="{Binding Path=IsChecked,
Mode=TwoWay}"
Visibility="{Binding IsFavoriteConfiguredAndInDA,
Converter={StaticResource boolToVisibility}}"
Checked="OnContentChanged"
Unchecked="OnContentChanged"/>
<Button Grid.Column="1"
Width="240"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Center"
AutomationProperties.AutomationId="AID_BtnLaunchFavorite"
Command="{Binding Path=LaunchFavorite}"
Content="{Binding Path=ModuleDisplayName}"
Cursor="Hand"
FontSize="{StaticResource UxLevel_5}"
Padding="24 12 2 12"
ToolTip="{Binding Path=ModuleDisplayName}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
I have another button called "Launch". Its basic functionality is to launch the tasks as per the selection in the above listbox items so that multiple tasks can be launched.Button XAML:
<Button Name="btnLaunch"
Width="80"
Height="25"
HorizontalAlignment="Left"
AutomationProperties.AutomationId="AUI_BtnLaunchForFavorite"
Command="{Binding LaunchCommand}"
Style="{StaticResource LaunchButtonStyle}"
Visibility="{Binding IsRIAMode,
Converter={StaticResource boolToVisibilityInverter}}">
Issue:
I want to enable/disable this launch button if atleast one item is selected and disable otherwise.How can i achieve? Pls help with some code snippets.
UPDATE:
Here is the launch command:
public ICommand LaunchCommand { get; private set; }
LaunchCommand = new DelegateCommand<object>(OnLaunch);
internal void OnLaunch(object sender)
{
var nFavItemToLaunchCount = Favorites.Count(favItem => favItem.IsChecked);
if (!IsSessionLimitReached(nFavItemToLaunchCount))
{
foreach (FavoriteItemViewModel favoriteItem in Favorites)
{
if (favoriteItem.IsChecked)
{
favoriteItem.LaunchFavorite.Execute(sender);
}
}
}
}
UPDATE 2:
I made the changes as per Krishna's comment:
LaunchCommand = new DelegateCommand<object>(OnLaunch,ToggleLaunch);
private bool ToggleLaunch(object obj)
{
if (Favorites.Count(i => i.IsChecked)!=0) //Favorites is the itemsource
{
return true;
}
return false;
}
Still the launch button is shown disabled always even when item is selected/checked.
UPDATE 3
After Krishna's further comment, i changed the implementation of the property IsChecked and also implemented INotifyPropertyChanged in the viewmodel.Still no luck!
public class FavoriteItemViewModel:INotifyPropertyChanged
{
public bool IsChecked
{
get
{
return m_IsChecked;
}
set
{
m_IsChecked = value;
OnPropertyChanged("IsChecked");
}
}
/// <summary>
/// Handler for property change
/// </summary>
/// <param name="propertyName">Name of property</param>
protected void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
There is another viewmodel "FavoriteContainerViewModel" that holds the collection of "FavoriteItemViewModel" and also implements INotifyPropertyChanged. This container view model is the place where i added the code mentioned in UPDATE 2
UPDATE 4:
Implementation of favorites:
public class FavoriteContainerViewModel : ViewModelBase, IModuleView
{
private readonly ObservableCollection<FavoriteItemViewModel> m_Favorites = new ObservableCollection<FavoriteItemViewModel>();
public ObservableCollection<FavoriteItemViewModel> Favorites
{
get { return m_Favorites; }
}
public FavoriteContainerViewModel()
{
LaunchCommand = new DelegateCommand<object>(OnLaunch, ToggleLaunch);
OnLoad();
}
private bool ToggleLaunch(object obj)
{
if (Favorites.Count(i => i.IsChecked) != 0)
{
return true;
}
return false;
//return true;
}
}
Note:ViewModelBase implements INotifyPropertyChanged
Update 5:
Problem now resolved using event based model. Implemented following:
FavoriteViewModel.cs
public event EventHandler ItemChecked;
public bool IsChecked
{
get
{
return m_IsChecked;
}
set
{
m_IsChecked = value;
if (ItemChecked != null)
{
ItemChecked(this, new EventArgs());
}
}
}
FavoriteItemContainerViewModel.cs
private void SubscribeFavoriteItemEvents(FavoriteItemViewModel favorite)
{
favorite.ItemChecked += ToggleLaunchButton;
}
private bool m_IsLaunchEnabled;
public bool IsLaunchEnabled
{
get
{
return m_IsLaunchEnabled;
}
set
{
m_IsLaunchEnabled = value;
OnPropertyChanged("IsLaunchEnabled");
}
}
Property IsLaunchEnabled is binded to the button to enable/disable.
You can enable/disable the Button based on the CheckBox.IsChecked property:
<Button Name="btnLaunch"
Width="80"
Height="25"
HorizontalAlignment="Left"
AutomationProperties.AutomationId="AUI_BtnLaunchForFavorite"
Command="{Binding LaunchCommand}"
Style="{StaticResource LaunchButtonStyle}"
Visibility="{Binding IsRIAMode,
Converter={StaticResource boolToVisibilityInverter}}"
IsEnabled="{Binding ElementName=CheckFavorite, Path=IsChecked}">
I am guessing the launch button is outside the listbox and user clicks it once the checkboxes are checked.
In that case, you need to add a condition in the 'CanExecute' part of your ICommand (LaunchCommand)
Lets assume your ICommand implementation in the constructor is something like
LaunchCommand = new RelayCommand(launchMethod);
private void launchMethod(object obj)
{
//do some work here
}
Now add canExecute part to your command by changing the initialisation
LaunchCommand = new DelegateCommand<object>(OnLaunch,checkCheckboxes);
and add this method
private bool checkCheckboxes(object obj)
{
//YourList is your itemsource
return YourList.Where(i=>i.IsChecked).Any();
}
Just change the above method to suit your needs
Update change your IsChecked property to below
private bool isChecked;
public bool IsChecked
{
get { return isChecked; }
set
{
isChecked = value;
OnPropertyChanged("IsChecked");
}
}
if (checkbox1.Checked && !checkbox2.Checked)
{
button1.Enable = true
}
else if (!checkbox1.Checked && checkbox2.Checked)
{
button1.Enable = false
}

Categories

Resources