CaliburnMicro - Binding list of items to ListBox - c#

I need to create a list that binds with items specified by name, boolean state and color.
Here is my ViewModel:
using Caliburn.Micro;
public class MainWindowViewModel :Screen
{
private List<string> _commandListSource;
private List<CommandItem> _commandsSource;
public List<CommandItem> CommandsSource
{
get
{
return _commandsSource;
}
set
{
_commandsSource = value;
NotifyOfPropertyChange(() => CommandsSource);
}
}
public MainWindowViewModel()
{
_commandListSource = new List<string>();
_commandListSource.Add("A");
_commandListSource.Add("B");
getsource();
NotifyOfPropertyChange(() => CommandsSource);
}
private void getsource()
{
_commandsSource = new List<CommandItem>();
foreach (var x in _commandListSource)
{
var ci = new CommandItem();
ci.CommandName = x;
ci.IsInTheOtherList = true;
_commandsSource.Add(ci);
}
}
}
CommandItem class:
public class CommandItem
{
public string CommandName;
public bool IsInTheOtherList;
public Color BGColor
{
get
{
if (IsInTheOtherList)
return Color.FromRgb(0, 0,255);
return Color.FromRgb(255, 255,0);
}
}
}
Xaml ListBox:
<ListBox x:Name="Source"
ItemsSource="{Binding CommandsSource , NotifyOnSourceUpdated=True}"
HorizontalAlignment="Left"
ScrollViewer.VerticalScrollBarVisibility="Visible"
VerticalAlignment="Stretch" MinWidth="100">
<ListBox.ItemTemplate>
<DataTemplate>
<DockPanel >
<TextBlock Text="*"/>
<Ellipse Fill="{Binding BGColor}" Width="10" Height="10"/>
<TextBlock Text="{Binding CommandName}"/>
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The problem is that the ListBox displays only * characters

I've solved this by changing the CommandItem class:
public class CommandItemClass : PropertyChangedBase
{
private string _commandName;
private bool _isInTheOtherList;
public SolidColorBrush BGColor
{
get
{
if (IsInTheOtherList)
return new SolidColorBrush(Color.FromRgb(0, 0, 255));
return new SolidColorBrush(Color.FromRgb(255, 255, 0));
}
}
public string CommandName
{
get
{
return _commandName;
}
set
{
_commandName = value;
NotifyOfPropertyChange(()=>CommandName);
}
}
public bool IsInTheOtherList
{
get
{
return _isInTheOtherList;
}
set
{
_isInTheOtherList = value;
NotifyOfPropertyChange(() => IsInTheOtherList);
NotifyOfPropertyChange(()=>BGColor);
}
}
}

Related

Dynamically changing tabitem via button command not working wfp

Im trying to create a function in a wpf program, where I can select an item in a listview, and press a button and it changes the tabitem and allows me to then edit the item from the listview that was selected. Im having issues with getting the tabitem to change for me.
For the navigation of my app, I have a ViewModelBase, which my AppointmentsViewModel inherits from. Inside the AppointmentsViewVM there is a tabcontrol with 4 items, by clicking each one it loads the requested view/viewmodel for that function.
This is not the only way I've tried to get this to work, Im currently on day 4. I could get the TabIndex to change in the TabControl earlier, but the tab would still not change for me. So I abandoned that and tried the below route (still no luck).
ViewModelBase
namespace MBR2.ViewModels
{
public class ViewModelBase : INotifyPropertyChanged
{
public ICommand MainMenuViewDogs_Command { get; set; }
public ICommand MainMenuViewAppointments_Command { get; set; }
private object _SelectedViewModel;
public object SelectedViewModel
{
get { return _SelectedViewModel; }
set
{
_SelectedViewModel = value;
OnPropertyChanged("SelectedViewModel");
}
}
public ViewModelBase()
{
MainMenuViewDogs_Command = new BaseCommand(OpenDogs);
MainMenuViewAppointments_Command = new BaseCommand(OpenAppointments);
}
private void OpenDogs(object obj)
{
SelectedViewModel = new DogsViewModel();
}
private void OpenAppointments(object obj)
{
SelectedViewModel = new AppointmentsViewModel();
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private bool _SelectedIndexView;
public bool SelectedIndexView
{
get { return _SelectedIndexView; }
set
{
_SelectedIndexView = value;
OnPropertyChanged("SelectedIndexView");
}
}
private bool _SelectedIndexAdd;
public bool SelectedIndexAdd
{
get { return _SelectedIndexAdd; }
set
{
_SelectedIndexView = value;
OnPropertyChanged("SelectedIndexAdd");
}
}
private bool _SelectedIndexEdit;
public bool SelectedIndexEdit
{
get { return _SelectedIndexEdit; }
set
{
_SelectedIndexView = value;
OnPropertyChanged("SelectedIndexEdit");
}
}
private bool _SelectedIndexDelete;
public bool SelectedIndexDelete
{
get { return _SelectedIndexDelete; }
set
{
_SelectedIndexView = value;
OnPropertyChanged("SelectedIndexDelete");
}
}
}
}
AppointmentsViewModel
{
public class AppointmentsViewModel : ViewModelBase
{
private AppointmentsAddVM _AppointmentsAddVM;
public AppointmentsAddVM AppointmentsAddVM { get { return _AppointmentsAddVM; } }
private AppointmentsEditVM _AppointmentsEditVM;
public AppointmentsEditVM AppointmentsEditVM { get { return _AppointmentsEditVM; } }
private AppointmentsDeleteVM _AppointmentsDeleteVM;
public AppointmentsDeleteVM AppointmentsDeleteVM { get { return _AppointmentsDeleteVM; } }
private AppointmentsViewVM _AppointmentsViewVM;
public AppointmentsViewVM AppointmentsViewVM { get { return _AppointmentsViewVM; } }
public ObservableCollection<object> ViewModelList { get; set; }
public AppointmentsViewModel()
{
this.ViewModelList = new ObservableCollection<object>();
_AppointmentsAddVM = new AppointmentsAddVM();
_AppointmentsEditVM = new AppointmentsEditVM();
_AppointmentsDeleteVM = new AppointmentsDeleteVM();
_AppointmentsViewVM = new AppointmentsViewVM();
this.ViewModelList.Add(_AppointmentsAddVM);
this.ViewModelList.Add(_AppointmentsEditVM);
this.ViewModelList.Add(_AppointmentsDeleteVM);
this.ViewModelList.Add(_AppointmentsViewVM);
}
}
}
AppointmentsView.xaml
<UserControl
x:Class="MBR2.Views.AppointmentsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:vms="clr-namespace:MBR2.ViewModels.Appointments"
xmlns:views="clr-namespace:MBR2.Views.Appointments"
xmlns:viewmodels="clr-namespace:MBR2.ViewModels"
d:DataContext="{d:DesignInstance Type=viewmodels:AppointmentsViewModel}"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<DataTemplate DataType="{x:Type vms:AppointmentsViewVM}">
<views:AppointmentsViewView />
</DataTemplate>
<DataTemplate DataType="{x:Type vms:AppointmentsAddVM}">
<views:AppointmentsAddView />
</DataTemplate>
<DataTemplate DataType="{x:Type vms:AppointmentsDeleteVM}">
<views:AppointmentsDeleteView />
</DataTemplate>
<DataTemplate DataType="{x:Type vms:AppointmentsEditVM}">
<views:AppointmentsEditView />
</DataTemplate>
</UserControl.Resources>
<Grid x:Name="Appointments" Width="Auto" Height="Auto">
<DockPanel HorizontalAlignment="Center"
Height="Auto"
LastChildFill="False"
VerticalAlignment="Top"
Width="Auto">
<TabControl x:Name="VMTabControl">
<TabItem x:Name="ViewTab"
TabIndex="0"
Header="View"
IsSelected="{Binding SelectedIndexView}"
Content="{Binding AppointmentsViewVM}"></TabItem>
<TabItem x:Name="AddTab"
TabIndex="1"
Header="Add"
IsSelected="{Binding SelectedIndexAdd}"
Content="{Binding AppointmentsAddVM}"></TabItem>
<TabItem x:Name="EditTab"
TabIndex="2"
Header="Edit"
IsSelected="{Binding SelectedIndexEdit}"
Content="{Binding AppointmentsEditVM}"></TabItem>
<TabItem x:Name="DeleteTab"
TabIndex="3"
Header="Delete"
IsSelected="{Binding SelectedIndexDelete}"
Content="{Binding AppointmentsDeleteVM}"></TabItem>
</TabControl>
</DockPanel>
</Grid>
</UserControl>
And the associated AppointmentsViewVM
namespace MBR2.ViewModels.Appointments
{
public class AppointmentsViewVM : ViewModelBase, INotifyPropertyChanged
{
private List<AppointmentsView_Wrapper> _AppointmentsView;
public List<AppointmentsView_Wrapper> AppointmentsView
{
get { return _AppointmentsView; }
set
{
_AppointmentsView = value;
OnPropertyChanged("AppointmentsView");
}
}
private List<string> _NameColumn = new List<string>();
public List<string> NameColumn
{
get { return _NameColumn; }
set
{
_NameColumn = value;
OnPropertyChanged("NameColumn");
}
}
private List<string> _ApptDateColumn = new List<string>();
public List<string> ApptDateColumn
{
get { return _ApptDateColumn; }
set
{
_ApptDateColumn = value;
OnPropertyChanged("ApptDateColumn");
}
}
private List<string> _ApptTimeColumn = new List<string>();
public List<string> ApptTimeColumn
{
get { return _ApptTimeColumn; }
set
{
_ApptTimeColumn = value;
OnPropertyChanged("ApptTimeColumn");
}
}
private List<string> _ApptVetColumn = new List<string>();
public List<string> ApptVetColumn
{
get { return _ApptVetColumn; }
set
{
_ApptVetColumn = value;
OnPropertyChanged("ApptVetColumn");
}
}
private List<string> _ApptCreatedColumn = new List<string>();
public List<string> ApptCreatedColumn
{
get { return _ApptCreatedColumn; }
set
{
_ApptCreatedColumn = value;
OnPropertyChanged("ApptCreatedColumn");
}
}
private List<int> _ApptIDColumn = new List<int>();
public List<int> ApptIDColumn
{
get { return _ApptIDColumn; }
set
{
_ApptIDColumn = value;
OnPropertyChanged("ApptIDColumn");
}
}
private string _AppointmentEdit_Enabled = "False";
public string AppointmentEdit_Enabled
{
get { return _AppointmentEdit_Enabled; }
set
{
_AppointmentEdit_Enabled = value;
OnPropertyChanged("AppointmentEdit_Enabled");
}
}
private AppointmentsView_Wrapper _ApptIDSelected;
public AppointmentsView_Wrapper ApptIDSelected
{
get { return _ApptIDSelected; }
set
{
AppointmentEdit_Enabled = "True";
_ApptIDSelected = value;
OnPropertyChanged("ApptIDSelected");
}
}
public AppointmentData AppointmentData = new AppointmentData();
public Messaging Messaging = new Messaging();
public ICommand AppointmentsListView_Command => new DelegateCommand<object>(AppointmentsListView_Clicked);
public ICommand EditSelection_Command => new DelegateCommand<object>(EditSelection_Clicked);
public AppointmentsViewVM()
{
BuildPage();
}
public async void BuildPage()
{
AppointmentsView = await AppointmentData.Appointments_GetAll();
foreach(var item in AppointmentsView)
{
ApptIDColumn.Add(item.ApptID);
NameColumn.Add(item.DogName);
ApptDateColumn.Add(item.ApptDate);
ApptTimeColumn.Add(item.ApptTime);
ApptVetColumn.Add(item.ApptVet);
ApptCreatedColumn.Add(item.ApptCreated.ToString("dd/mm/yyyy"));
}
}
public void AppointmentsListView_Clicked(object obj)
{
Messaging.ShowAlert(ApptIDSelected.ApptID.ToString());
}
public void EditSelection_Clicked(object obj)
{
bool result = Messaging.AskQuestion(ApptIDSelected.ApptID.ToString());
if(result)
{
SelectedIndexView = false;
SelectedIndexAdd = false;
SelectedIndexEdit = true;
SelectedIndexDelete = false;
OnPropertyChanged("SelectedIndexView");
OnPropertyChanged("SelectedIndexAdd");
OnPropertyChanged("SelectedIndexEdit");
OnPropertyChanged("SelectedIndexDelete");
}
else
{
Messaging.ShowAlert("no");
}
}
}
}
Here's a minimal reproduction of something where you select in a listbox and that then selects a corresponding tab in a tabcontrol.
This is very minimal but we can perhaps imagine a more sophisticated viewmodel per item in the listbox with name and viewmodel or something.
This is mainwindow.
<Window.Resources>
<DataTemplate DataType="{x:Type local:Avm}">
<local:Aview/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Bvm}">
<local:Bview/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Cvm}">
<local:Cview/>
</DataTemplate>
</Window.Resources>
<Window.DataContext>
<local:MainWindowViewmodel/>
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ListBox ItemsSource="{Binding ViewModels}"
x:Name="lb"
>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ViewModelName}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TabControl Grid.Column="1"
ItemsSource="{Binding ViewModels}"
SelectedItem="{Binding ElementName=lb, Path=SelectedItem, Mode=TwoWay}"
>
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock
Text="{Binding ViewModelName}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding}"/>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Grid>
I have only done 3 views and viewmodels.
Note that the selecteditem of the listbox is bound twoway to the tabcontrol.
I have matching views and viewmodels A, B and C
MainWindowViewModel
public class MainWindowViewmodel : ViewModelBase
{
public ObservableCollection<Object> ViewModels { get; set; } = new ObservableCollection<Object>{
new Avm{ViewModelName="A viewmodel" },
new Bvm{ViewModelName="B viewmodel" },
new Cvm{ViewModelName="C viewmodel" }
};
}
Both the itemssource of listbox and tabcontrol are bound to that collection of viewmodels. Which are, as I mentioned, as simple as you get really.
Viewmodelbase
public class ViewModelBase : INotifyPropertyChanged
{
public string ViewModelName { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
Avm, Bvm and Cvm just inherit from that.
An example usercontrol view.
<Grid>
<TextBlock Text="{Binding ViewModelName}"/>
</Grid>
</UserControl>
When I spin that up, select and select an item in the listbox the matching tab is selected. And vice versa. Select a tab and it selects the same one in the listbox.

Binding value from parent Page ViewModel to UserControl

I write new WPF MVVM app.
I new in WPF.
I have problem with binding value to StageControl from MainPageModelView.
StageControl is in MainPage.
I know how binding value to element in MainPage, but I can't binding value to StageControl in this same way.
How can I binding value from MainPageModelView to StageControl?
Code:
MainPage.xaml
<my:StageControl x:Name="stageControl1" StageIsActive="true" StageName="{Binding Stage.Name}" Grid.Row="0" Grid.Column="0"/>
...
<Label x:Name="lbTest" Content="{Binding Test}" HorizontalAlignment="Left" Margin="104,10,0,0" VerticalAlignment="Top" Height="56" Width="68"/>
StageControl.xaml.cs
public partial class StageControl : UserControl
{
string stageName;
bool stageIsActive;
public StageControl()
{
InitializeComponent();
}
public bool StageIsActive
{
get { return this.stageIsActive; }
set { this.stageIsActive = SetStageControlStatus(value); }
}
public string StageName
{
get { return this.stageName; }
set { this.stageName = SetStageName(value); }
}
private bool SetStageControlStatus(bool value)
{
if (value)
{
this.outRing.Visibility = Visibility.Visible;
return true;
}
else
{
this.outRing.Visibility = Visibility.Hidden;
return false;
}
}
private string SetStageName(string value)
{
this.text.Text = value;
return this.text.Text;
}
}
MainPageViewModel.cs
class MainPageViewModel
{
public List<Stage> Stages = new List<Stage>();
public Stage stage = new Stage(0, "Test", true);
public MainPageViewModel()
{
Stages = Stage.GetStages();
}
public string Test
{
get { return "Testowy Label"; }
set { }
}
}
Edit:
MainPage.xaml.css
public MainPage()
{
InitializeComponent();
MainPageViewModel viewModel = new MainPageViewModel();
this.DataContext = viewModel;
}
I solved the problem.
First I add dependency property to StageControl.xaml.cs, then I add binding to StageControl.xaml
...
x:Name="Stage"
...
<TextBlock x:Name="text" TextWrapping="Wrap" Text="{Binding ElementName=Stage, Path=StageName}" TextAlignment="Center" FontSize="12" HorizontalAlignment="Center" VerticalAlignment="Center"/>
public Stage Stage {get;set;} = new Stage(0,"Test",true);
u need to make property instead of public variable

Get checked items from a listbox

I'm just getting used to MVVM and want to do without the code-behind and define everything in the view-models.
the combobox represents several selection options (works). I would like to query the elements that have been checked.
Unfortunately I can't access them. The textbox should display all selected elements as concatenated string.
View-Model
class MainViewModel : BaseViewModel
{
#region Fields
private ObservableCollection<EssayTypeViewModel> _essayTypes;
private EssayTypeViewModel _selectedEssayTypes;
#endregion
public ObservableCollection<EssayTypeViewModel> EssayTypes
{
get => _essayTypes;
set
{
if (_essayTypes == value) return;
_essayTypes = value; OnPropertyChanged("EssayTypes");
}
}
public EssayTypeViewModel SelectedEssayTypes
{
get => _selectedEssayTypes;
set { _selectedEssayTypes = value; OnPropertyChanged("SelectedEssayTypes"); }
}
public MainViewModel()
{
// Load Essay Types
EssayTypeRepository essayTypeRepository = new EssayTypeRepository();
var essayTypes = essayTypeRepository.GetEssayTypes();
var essayTypeViewModels = essayTypes.Select(m => new EssayTypeViewModel()
{
Text = m.Text
});
EssayTypes = new ObservableCollection<EssayTypeViewModel>(essayTypeViewModels);
}
}
XAML
<ListBox x:Name="Listitems" SelectionMode="Multiple" Height="75" Width="200" ItemsSource="{Binding EssayTypes}" >
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Text}" IsChecked="{Binding Checked}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBox Text="{Binding Path=SelectedEssayTypes}" Grid.Column="0" Width="160" Height="25" Margin="0,140,0,0"/>
You could hook up an event handler to the PropertyChanged event of all EssayTypeViewModel objects in the EssayTypes collection and raise the PropertyChanged event for a read-only property of the MainViewModel that returns all selected elements as concatenated string:
public MainViewModel()
{
// Load Essay Types
EssayTypeRepository essayTypeRepository = new EssayTypeRepository();
var essayTypes = essayTypeRepository.GetEssayTypes();
var essayTypeViewModels = essayTypes.Select(m =>
{
var vm = EssayTypeViewModel()
{
Text = m.Text
};
vm.PropertyChanged += OnPropertyChanged;
return vm;
});
EssayTypes = new ObservableCollection<EssayTypeViewModel>(essayTypeViewModels);
}
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Checked")
OnPropertyChanged("SelectedItems");
}
public string SelectedItems => string.Join(",", EssayTypes.Where(x => x.Checked).ToArray());
This requires the EssayTypeViewModel class to implement the INotifyPropertyChanged interface (by for example deriving from your BaseViewModel class).
You can apply Mode = Two way on the checkbox binding.
<CheckBox Content="{Binding Text}" IsChecked="{Binding Checked, Mode=TwoWay}"/>
then you can iterate through the essay types collection to check if the item entry was checked.
For ex. Sample code can be:
foreach (var essayTypeInstance in EssayTypes)
{
if(essayTypeInstance.Checked)
{
// this value is selected
}
}
Hope this helps.
mm8 answer works. In the meantime i came up with another approach. Not 100% MVVM compatible but it works and is quite simple.
XAML
<ListBox x:Name="ListItems" SelectionMode="Multiple" Height="75" Width="200" ItemsSource="{Binding CollectionOfItems}" >
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding Checked, Mode=TwoWay}" Unchecked="GetCheckedElements" Checked="GetCheckedElements" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBox Text="{Binding SelectedItemsString, UpdateSourceTrigger=PropertyChanged}" Grid.Column="0" Width="160" Height="25" Margin="0,140,0,0"/>
Code Behind
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
}
private void GetCheckedElements(object sender, RoutedEventArgs e)
{
(DataContext as MainViewModel)?.FindCheckedItems();
(DataContext as MainViewModel)?.ConcatSelectedElements();
}
}
Model
public class Items
{
public bool Checked { get; set; }
public string Name { get; set; }
}
ItemsViewModel (BaseViewModel only implements INotifyPropertyChanged)
class ItemsViewModel : BaseViewModel
{
private bool _checked;
private string _name;
public bool Checked
{
get => _checked;
set
{
if (value == _checked) return;
_checked = value;
OnPropertyChanged("Checked");
}
}
public string Name
{
get => _name;
set
{
if (value == _name) return;
_name = value;
OnPropertyChanged("Name");
}
}
}
MainViewModel
public class MainViewModel : BaseViewModel
{
private string _selectedItemsString;
private ObservableCollection<Items> _selectedItems;
public ObservableCollection<Items> CollectionOfItems { get; set; }
public ObservableCollection<Items> SelectedItems
{
get => _selectedItems;
set
{
_selectedItems = value;
OnPropertyChanged("SelectedItems");
}
}
public string SelectedItemsString
{
get => _selectedItemsString;
set
{
if (value == _selectedItemsString) return;
_selectedItemsString = value;
OnPropertyChanged("SelectedItemsString");
}
}
public MainViewModel()
{
CollectionOfItems = new ObservableCollection<Items>();
SelectedItems = new ObservableCollection<Items>();
CollectionOfItems.Add(new Items { Checked = false, Name = "Item 1" });
CollectionOfItems.Add(new Items { Checked = false, Name = "Item 2" });
CollectionOfItems.Add(new Items { Checked = false, Name = "Item 3" });
}
public void FindCheckedItems()
{
CollectionOfItems.Where(x => x.Checked).ToList().ForEach(y => SelectedItems.Add(y));
}
public void ConcatSelectedElements()
{
SelectedItemsString = string.Join(", ", CollectionOfItems.Where(x => x.Checked).ToList().Select(x => x.Name)).Trim();
}
}

C#-Accessing .xaml created checkbox/listbox

Is there a way to verify if checkbox and a specific item in a listbox has been selected, when it was created in .xaml?
I am trying to access these elements from a different class rather than the ViewModel.
I want to be able to do something as follows;
if (First_CheckBox.Ischecked && LocationBox.SelectedItem == "FirstValue")
{
do something;
}
else
{
do something else;
}
.XAML Code:
<CheckBox x:Name="First_CheckBox" IsChecked="{Binding Check, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" Content="Integral "/>
<ListBox x:Name="LocationBox" ItemsSource="{Binding LocationList}" SelectionMode="Single" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" Margin="0,5" Width="100" HorizontalAlignment="Left" BorderThickness="1" Background="#FFF0ECEC">
Current Code:
namespace ValueClearanceCalculator.ViewModels
{
class MainWindowViewModel : CommonBase
{
public delegate void PropertyChangedHandler(object obj);
public static event PropertyChangedHandler MainVMPropertyChanged = delegate { };
public MainWindowViewModel()
{
CalculateAndDrawPatternCommand = new CalculatePatternCommand(this);
}
private public bool _Check;
public bool Check
{
get
{
return _Check;
}
set
{
_Check = value;
RaisePropertyChanged("Check");
_C = _A;
double temp;
bool result = double.TryParse(_C, out temp);
if (result == false) { MessageBox.Show("Can Not Convert A to C"); }
else { FrontPanelVariables.C = temp * 25.4; }
RaisePropertyChanged("C");
_F = ".157";
FrontPanelVariables.F = .157;
RaisePropertyChanged("F");
}
}

DataGridTemplateColumn update

I'm reworking an old control to WPF. I need to make a datagrid which displays a list of alarms. The first column of the datagrid is a datagridtemplate column which holds a flag icon and the date. When the user presses the button the alarms are acknowledged and the flag icon has to disappear. I'm using an MVVM pattern.
The problem is that I cannot seem to update the flag in the datagridtemplate column. When I change the acknowledge status from 0 to 1 (the alarm was ackonwledged), the flag does not disappear. When I reload the control and get the alarms again from the server, the flag does not show up again indicating that its status has actually been updated in the server. So somehow my code is working but my UI is not getting updated. I also tried to change the alarm's description in the same way and that column does get updated. (MainViewModelBase implements INotifyPropertyChanged)
The view
<DataGrid x:Class="Kwa.Presentation.Views.AlarmList.AlarmList"
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:Kwa.Presentation.Views.AlarmList"
xmlns:components="clr-namespace:Kwa.Presentation.Components"
xmlns:converters="clr-namespace:Kwa.Presentation.Converters"
xmlns:Trans="clr-namespace:Kwa.Presentation.Resources"
mc:Ignorable="d"
d:DesignHeight="500" d:DesignWidth="750"
ItemsSource="{Binding Alarms}"
SelectedItem="{Binding SelectedAlarm}"
IsSynchronizedWithCurrentItem="True"
CanUserResizeColumns="True" IsReadOnly="True" CanUserReorderColumns="False" CanUserSortColumns="False" SelectionMode="Single" CanUserAddRows="False"
Background="White" RowHeaderWidth="0" AutoGenerateColumns="False" GridLinesVisibility="None" RowHeight="{Binding Rowheight}" FrozenColumnCount = "1"
ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto"
x:Name="AlarmFramework"
SizeChanged="AlarmFramework_SizeChanged"
>
<DataGrid.Resources>
<converters:AlarmSeverityToColorConverter x:Key="AlarmSeverityToColorConverter"/>
<converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
<converters:InvertedBoolToVisibilityConverter x:Key="InvertedBoolToVisibilityConverter"/>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn Header="{x:Static Trans:TranslatedResources.AlarmColumnHeaderTime}" Width="auto" HeaderStyle="{StaticResource WithButt}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<components:FlagControl VerticalAlignment="Center" Height="15" Width="15" FlagColor="{Binding Severity, Converter={StaticResource AlarmSeverityToColorConverter}}"
Visibility="{Binding AckStatus, Converter={StaticResource InvertedBoolToVisibilityConverter}, Mode=TwoWay}"/>
<TextBlock Text="{Binding DateTimeString}" Padding="10,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center"/>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="{x:Static Trans:TranslatedResources.AlarmColumnHeaderSeverity}" Binding="{Binding SeverityString}" Width="auto" HeaderStyle="{StaticResource WithoutButt}"/>
<DataGridTextColumn Header="{x:Static Trans:TranslatedResources.AlarmColumnHeaderDescription}" Binding="{Binding Description}" d:Width="400" Width="*" HeaderStyle="{StaticResource WithoutButt}"/>
</DataGrid.Columns>
</DataGrid>
The AlarmList View Model
public class AlarmListViewModel : MainViewModelBase
{
#region Properties
private ObservableCollection<AlarmEntryViewModel> _alarms = new ObservableCollection<AlarmEntryViewModel>();
public ObservableCollection<AlarmEntryViewModel> Alarms
{
get { return _alarms; }
set
{
_alarms = value;
RaisePropertyChanged(() => Alarms);
}
}
private AlarmEntryViewModel _selectedAlarm;
public AlarmEntryViewModel SelectedAlarm
{
get { return _selectedAlarm; }
set
{
_selectedAlarm = value;
RaisePropertyChanged(() => SelectedAlarm);
}
}
private int _acknowledgeAllowed;
public int AcknowledgeAllowed
{
get { return _acknowledgeAllowed; }
set
{
_acknowledgeAllowed = value;
RaisePropertyChanged(() => AcknowledgeAllowed);
}
}
private readonly IActionCommand _acknowledgeCommand;
public IActionCommand AcknowledgeCommand
{
get { return _acknowledgeCommand; }
}
public int MaxAcknowledgedAlarm;
public double RowHeight { get; set; }
public AlarmEntryViewModel AlarmToSend { get; set; }
#endregion
#region Constructor
public AlarmListViewModel()
{
if (!IsInDesignMode)
{
RowHeight = 30;
}
//Add command
_acknowledgeCommand = new ActionCommand<double>(p => Acknowledge(p));
}
#endregion
#region Private Methods
private void Acknowledge(double parameter)
{
if (AcknowledgeAllowed == 1)
{
try
{
//Get Datagrid width
double DatagridWidth = (double)parameter;
//Calculate the amount of fully visible alarms
int AmountVisible = (int)Math.Floor(DatagridWidth / RowHeight);
if (Alarms.Count < AmountVisible)
{
AlarmToSend = Alarms[Alarms.Count - 1];
foreach(AlarmEntryViewModel alarm in Alarms)
{
alarm.AckStatus = true;
alarm.Description = "Iets nieuw";
}
}
else
{
//Send the last visible alarm, 0 based => -1
AlarmToSend = Alarms[AmountVisible - 1];
//Go to next visible alarm
SelectedAlarm = Alarms[AmountVisible];
}
//Acknowledge alarms
_proxy.Send(AlarmToSend.AlarmNumber);
}
catch (Exception ex)
{
_viewManager.ShowDialog(new MessageDialogViewModel()
{
AskAnswer = false,
Text = ex.Message,
Title = TranslatedResources.AlarmAckSendErrorTitle,
});
}
}
else
{
_viewManager.ShowDialog(new MessageDialogViewModel()
{
AskAnswer = false,
Text = TranslatedResources.AlarmAcknErrorMessage,
Title = TranslatedResources.AlarmAcknErrorTitle,
});
}
}
#endregion
The AlarmListEntry view model
public class AlarmEntryViewModel : MainViewModelBase
{
#region Fields
private readonly IViewManager _viewManager;
private readonly IDockManager _dockManager;
private string _description;
#endregion
#region Constructor
public AlarmEntryViewModel()
{
}
#endregion
#region Model & Proxy
private Alarm _model;
public Alarm Model
{
set { _model = value; }
}
public AlarmListServiceProxy Proxy { get; set; }
#endregion
#region Properties
public DateTime Time { get { return _model.Time; } }
public string DateTimeString { get { return _model.Time.ToString("dd/MM/yyyy hh:mm:ss"); } }
public int Severity { get { return _model.Severity; } }
public string SeverityString
{
get
{
if (_model.Severity == 0)
return "Melding";
if (_model.Severity == 1)
return "Waarschuwing";
if (_model.Severity == 2)
return "Fout";
else
return "Niet gekend";
}
}
public string Description
{
get
{
//string substring = _model.Description.Substring(_model.Description.Length - 1);
//if ( substring.Equals("\n"))
//{
// return _model.Description.Substring(0, _model.Description.Length - 1);
//}
//else
// return _model.Description;
return _description;
}
set
{
_description = value;
RaisePropertyChanged(() => Description);
}
}
public int AlarmNumber { get { return _model.Number; } }
public int AcknStatus { get { return _model.AcknStatus; } }
private bool _ackStatus;
public bool AckStatus
{
get
{
if (_model.AcknStatus == 0)
return false;
else
return true;
}
set
{
_ackStatus = value;
RaisePropertyChanged(() => AckStatus);
}
}
#endregion
}
You set _ackStatus in the setter but doesn't return the value of this field from the getter in AlarmEntryViewModel. Do this:
private bool _ackStatus;
public bool AckStatus
{
get
{
return _ackStatus;
}
set
{
_ackStatus = value;
RaisePropertyChanged(() => AckStatus);
}
}
Or set the _model.AcknStatus field in the setter:
private bool _ackStatus;
public bool AckStatus
{
get
{
if (_model.AcknStatus == 0)
return false;
else
return true;
}
set
{
_ackStatus = value;
_model.AcknStatus = value ? 1 : 0;
RaisePropertyChanged(() => AckStatus);
}
}

Categories

Resources