Dynamic generation of UI Components in WPF - c#

Alright this is a tricky situation. I have 2 xaml files in my WPF project, VoltageChannelView.xaml and VoltageView.Xaml, In my VoltageView.xaml I have divided the Grid into 3 rows as follows:
VoltageView:
<Grid Style="{DynamicResource styleBackground}" >
<Grid.RowDefinitions>
<RowDefinition Height="70" />
<RowDefinition />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" >
</Grid>
<Grid Name="ContentGrid" Grid.Row="1" Height="Auto" Width="Auto">
<Grid.RowDefinitions>
<RowDefinition Name="Label11" />
<RowDefinition Name="Label22" />
<RowDefinition Name="Label33" />
<RowDefinition Name="Label44" />
<RowDefinition Name="Label55" />
<RowDefinition Name="Label66" />
<RowDefinition Name="Label77" />
<RowDefinition Name="Label88" />
<RowDefinition Name="Label99" />
</Grid.RowDefinitions>
</Grid>
<Grid Grid.Row="2" >
<Button Content="Bavaria 2" FontSize="13" Height="25" HorizontalAlignment="Left" Margin="30,0,0,0" Name="RefreshBtn" VerticalAlignment="Center" Width="105" />
<Button Content="Redhook" FontSize="13" Height="25" HorizontalAlignment="Center" Margin="0,0,0,0" Name="Refresh1Btn" VerticalAlignment="Center" Width="105" />
<Button Content="Bavaria 1" FontSize="13" Height="25" HorizontalAlignment="Right" Margin="0,0,30,0" Name="Refresh2Btn" VerticalAlignment="Center" Width="105" />
</Grid>
</Grid>
Now you can notice Grid.Row="1" where I have divided the grid into 9 rows.
VoltageChannelView:
<CheckBox Content="On" Grid.Column="3" Height="Auto" HorizontalAlignment="Center" Margin="0" Name="On" VerticalAlignment="Center" />
<Button Content="Set" Grid.Column="1" Height="23" HorizontalAlignment="Center" Margin="85,0,0,0" Name="Set" VerticalAlignment="Center" Width="75" />
<TextBox Grid.Column="1" Height="23" HorizontalAlignment="Center" Margin="0,0,80,0" Name="textBox1" VerticalAlignment="Center" Width="70" />
<Label Content="VDD__Main" Grid.Column="0" Height="15" HorizontalAlignment="Center" Margin="0,0,70,0" Name="VoltageLabel" VerticalAlignment="Center" />
<Label Content="0.0 V" Grid.Column="2" Height="15" HorizontalAlignment="Center" Margin="0" Name="CurrentLabel" VerticalAlignment="Center" />
Now I have 3 buttons in my Grid.Row="2" and my requirement is, when I click "Bavaria 2" Button, I want the content of VoltageChannelView to be placed in my VoltageView Grid.Row="1". Here is the trick, it should dynamically generate the entire content 5 times. I.e. In 9 rows present in Grid.Row="1", the content of VoltageChannelView should appear in first 5 rows, one each in each row.
On Click "Bavaria1" it should generate the content 8 times and so on. Basically Is it possible in WPF to generate the contents of VoltageChannelView "n" times based on each button click and display it in my VoltageView??????

Yes it is. You can create a VoltageChanelView collection , and then create a datatemplate for it. i think this way it`s easier for you to display it.
First I don't really understand what you are trying to accomplish with all those grid rows and so on. but maybe using a listview instead a grid divided in 9 rows will make it simpler.
Implement this classes...
namespace TestWpf
{
class VoltageChangeModel : INotifyPropertyChanged
{
private int _Voltage = 0;
private string _ChanelName = "";
private Brush color = Brushes.Blue;
public Brush Color
{
set
{
if (value != color)
{
onPropertyChanged("Color");
color = value;
}
}
get
{
return color;
}
}
public int Voltage
{
set
{
if (value != _Voltage)
{
onPropertyChanged("Voltage");
_Voltage = value;
}
}
get
{
return _Voltage;
}
}
public String ChanelName
{
set
{
if (value != _ChanelName)
{
onPropertyChanged("ChanelName");
_ChanelName = value;
}
}
get
{
return _ChanelName;
}
}
public VoltageChangeModel(int Voltage, string ChanelName, Brush Color)
{
this.ChanelName = ChanelName;
this.Voltage = Voltage;
this.Color = Color;
}
public override string ToString()
{
return _ChanelName;
}
public void onPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
next this clas....
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
namespace TestWpf
{
class ChanellList : ObservableCollection<VoltageChangeModel>
{
}
}
in the mainWindow this code after <window ,,,,,,,,,,,>
<Grid>
<ListBox x:Name="myViewChannelList" HorizontalAlignment="Left" Height="161" ItemsSource="{Binding}" Margin="82,38,0,0" VerticalAlignment="Top" Width="187">
<ListBox.ItemTemplate>
<DataTemplate >
<StackPanel Background="{Binding Path=Color}">
<Label Content="{Binding Path=Voltage}" ></Label>
<Label Content="{Binding Path=ChanelName}"></Label>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
and then in code behind set the data context.
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace TestWpf
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ChanellList myChanels = new ChanellList();
myChanels.Add(new VoltageChangeModel(30,"Channel 1 " , Brushes.Blue ));
myChanels.Add(new VoltageChangeModel(30, "Channel 1 ", Brushes.Red));
myViewChannelList.DataContext = myChanels;
}
}
}
You have the source for download here http://mihairadulescu.com/download/TestWpf.rar

Related

Editing copies of an ObservableCollection's Object without editing the ObservableCollection

I have a WPF form that I want to use to manipulate a database table. To get the data out of the database I use Entity Framework Core. I try to follow the MVVM pattern.
So I have a Model called Employee with a number of string properties like Firstname and so on.
The form has a ListView that shows an ObservableCollection of Employee. Further I have a number of TextBoxes to display and manipulate the properties of single Employee objects. The selectedMemberPath of the ListView is bound to a property SelectedEmployee. The setter of SelectedEmployee than copies it's own properties to EditedEmployee. The TextBoxes are bound to EditedEmployee. The idea is, that I don't want to directly edit the ObservableCollection. This should only happen if a save button is clicked.
This is my view model.
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using XdcCore.Models;
using XdcCore.ViewModels.Commands;
namespace XdcCore.ViewModels
{
class EmployeeEditorVM : List<Employee>, INotifyPropertyChanged
{
public EmployeeSaveCommand EmployeeSaveCommand { get; set; }
public EmployeeEditorVM()
{
EmployeeSearch();
EmployeeSaveCommand = new EmployeeSaveCommand(this);
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private string employeeSearchText;
public string EmployeeSearchText
{
get { return employeeSearchText; }
set
{
employeeSearchText = value;
OnPropertyChanged("EmployeeSearch");
EmployeeSearch();
}
}
private Employee selectedEmployee;
public Employee SelectedEmployee
{
get { return selectedEmployee; }
set
{
selectedEmployee = value;
OnPropertyChanged("SelectedEmployee");
EditedEmployee = SelectedEmployee;
}
}
private Employee editedEmployee;
public Employee EditedEmployee
{
get { return editedEmployee; }
set
{
editedEmployee = value;
OnPropertyChanged("EditedEmployee");
}
}
private ObservableCollection<Employee> employees;
public ObservableCollection<Employee> Employees
{
get { return employees; }
set
{
employees = value;
OnPropertyChanged("Employees");
}
}
public void EmployeeSearch()
{
using (var context = new XdcContext())
{
if (employeeSearchText != null)
{
var _employees = context.Employee
.Where(x => x.Firstname.Contains(employeeSearchText));
Employees = new ObservableCollection<Employee>(_employees);
}
else
{
var _employees = context.Employee.Select(x => x);
Employees = new ObservableCollection<Employee>(_employees);
}
}
}
public void EmployeeSave()
{
using (var context = new XdcContext())
{
var entity = context.Employee.First(x => x.IdEmployee == SelectedEmployee.IdEmployee);
{
entity.Firstname = SelectedEmployee.Firstname;
entity.Lastname = SelectedEmployee.Lastname;
entity.Initials = SelectedEmployee.Initials;
context.SaveChanges();
}
EmployeeSearch();
}
}
}
}
this is my View:
<Window
x:Class="XdcCore.Views.Editors.EmployeeEditor"
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:local="clr-namespace:XdcCore.Views.Editors"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:XdcCore.ViewModels"
Title="Employee"
Width="800"
Height="450"
mc:Ignorable="d">
<Window.Resources>
<vm:EmployeeEditorVM x:Key="vm" />
</Window.Resources>
<Grid DataContext="{StaticResource vm}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300" />
<ColumnDefinition Width="115*" />
<ColumnDefinition Width="277*" />
</Grid.ColumnDefinitions>
<!-- left column -->
<Border BorderBrush="DarkGray" BorderThickness="1">
<Grid Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="aUTO" />
</Grid.RowDefinitions>
<Label
Grid.Row="0"
Margin="3,3,3,3"
Content="Filter:" />
<TextBox
x:Name="TextBoxSearch"
Grid.Row="1"
Height="25"
Margin="3,0,3,3"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Center"
Text="{Binding EmployeeSearchText, Mode=TwoWay}" />
<ListView
x:Name="ListViewOverview"
Grid.Row="2"
Margin="3,0,3,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ItemsSource="{Binding Employees, Mode=OneWay}"
SelectedItem="{Binding SelectedEmployee, Mode=OneWayToSource}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Initials}" />
<TextBlock Text=" : " />
<TextBlock Text="{Binding Firstname}" />
<TextBlock Text=" " />
<TextBlock Text="{Binding Lastname}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Grid Grid.Row="3">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Button
x:Name="ButtonDelete"
Grid.Column="0"
Height="25"
Margin="3,3,3,3"
Content="Delete"
IsEnabled="False" />
<Button
x:Name="ButtonNew"
Grid.Column="1"
Height="25"
Margin="3,3,3,3"
Content="Add New ..."
IsEnabled="True" />
</Grid>
</Grid>
</Border>
<!-- right Column -->
<Grid Grid.Column="1" Grid.ColumnSpan="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- right column, first row -->
<Border
Grid.Row="0"
BorderBrush="DarkGray"
BorderThickness="1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="200" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label
Grid.Row="0"
Grid.Column="0"
HorizontalAlignment="Right"
Content="First Name" />
<Label
Grid.Row="1"
Grid.Column="0"
HorizontalAlignment="Right"
Content="Last Name" />
<Label
Grid.Row="2"
Grid.Column="0"
HorizontalAlignment="Right"
Content="Initials" />
<Label
Grid.Row="3"
Grid.Column="0"
HorizontalAlignment="Right"
VerticalContentAlignment="Center"
Content="ID" />
<Label
Grid.Row="4"
Grid.Column="0"
HorizontalAlignment="Right"
VerticalContentAlignment="Center"
Content="RCU" />
<Label
Grid.Row="5"
Grid.Column="0"
HorizontalAlignment="Right"
VerticalContentAlignment="Center"
Content="RCT" />
<TextBox
x:Name="TextBoxFirstName"
Grid.Row="0"
Grid.Column="1"
Margin="0,3,3,3"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Center"
Text="{Binding EditedEmployee.Firstname, Mode=TwoWay}" />
<TextBox
x:Name="TextBoxLastName"
Grid.Row="1"
Grid.Column="1"
Margin="0,3,3,3"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Center"
Text="{Binding EditedEmployee.Lastname, Mode=TwoWay}" />
<TextBox
x:Name="TextBoxInitials"
Grid.Row="2"
Grid.Column="1"
Margin="0,3,3,3"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Center"
Text="{Binding EditedEmployee.Initials, Mode=TwoWay}" />
<TextBox
x:Name="TextBoxId"
Grid.Row="3"
Grid.Column="1"
Margin="0,3,3,3"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Center"
IsReadOnly="True" />
<TextBox
x:Name="TextBoxRCU"
Grid.Row="4"
Grid.Column="1"
Margin="0,3,3,3"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Center"
IsReadOnly="True" />
<TextBox
x:Name="TextBoxRCT"
Grid.Row="5"
Grid.Column="1"
Margin="0,3,3,3"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Center"
IsReadOnly="True" />
</Grid>
</Border>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Button
x:Name="ButnSave"
Grid.Column="1"
Width="76"
Height="25"
Margin="60,3,60,0"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Command="{Binding EmployeeSaveCommand}"
Content="Save"
IsEnabled="True" />
</Grid>
<!-- Add new -->
</Grid>
</Grid>
</Grid>
</Window>
In other words: I want to click on an item in the list view, it's details are shown in the text boxes. I can change the text in the text boxes but the changes are not applied to the observable collection (or even database) until I click "save". The problem is, that exactly that happens: when I edit text in the text boxes the changes are also shown in the list view. And I can#t see why.
So, I got the concept of "copy vs point" of a variable wrong.
I had two solutions for my problem.
To my Employee model I added the method Copy:
public partial class Employee
{
public int IdEmployee { get; set; }
public string Initials { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public string Rcu { get; set; }
public DateTime Rct { get; set; }
public Employee Copy()
{
return (Employee)this.MemberwiseClone();
}
}
Then I Changed my ViewModel so that EditedEmployee is a copy of SelectedEmployee
private Employee selectedEmployee;
public Employee SelectedEmployee
{
get { return selectedEmployee; }
set
{
selectedEmployee = value;
OnPropertyChanged("SelectedEmployee");
if (SelectedEmployee != null)
{
EditedEmployee = SelectedEmployee.Copy();
}
}
}
private Employee editedEmployee;
public Employee EditedEmployee
{
get { return editedEmployee; }
set
{
editedEmployee = value;
OnPropertyChanged("EditedEmployee");
}
}
The problem with this approach is, that if I mess around with the database and then need to run Scaffold-DbContext (I prefer the code-first approach of EFC) again, I would have to modify all models again. A solution to that might be some a second, modified Model that inherits from the original Model and then adds the Copy method.
My second approach is to bind the ListView via SelectedIndex instead of SelectedItem.
<ListView
...
ItemsSource="{Binding Employees, Mode=OneWay}"
SelectedIndex="{Binding SelectedItemIndex, Mode=TwoWay}">
In the ViewModel this is then represented by an int property. If this int is set (and >= 0) Employee gets copied EmployeeWorkingCopy. Furthermore if EmployeeWorkingCopy is set a single Employee dubbed EditedEmployee is set as the Employee of the working copy with the selected index.
private int selectedItemIndex;
public int SelectedItemIndex
{
get { return selectedItemIndex; }
set
{
selectedItemIndex = value;
if (SelectedItemIndex >= 0)
EmployeesWorkingCopy = new ObservableCollection<Employee>(Employees);
}
}
private Employee editedEmployee;
public Employee EditedEmployee
{
get { return editedEmployee; }
set
{
editedEmployee = value;
OnPropertyChanged("EditedEmployee");
}
}
private ObservableCollection<Employee> employeesWorkingCopy;
public ObservableCollection<Employee> EmployeesWorkingCopy
{
get { return employeesWorkingCopy; }
set
{
employeesWorkingCopy = value;
EditedEmployee = EmployeesWorkingCopy[SelectedItemIndex];
}
}
Thanks a lot for pointing out my misconception.

Clone a GridColumn keeping the event handlers(ClickEvents) and properties of its elements same

I have an application with 4 tabs. In the first three tabs, I have some GridColumns filled with elements (Buttons, CheckBoxes, ComboBoxes, Labels etc). Each tab have different elements.
What I want to do, is to copy/clone only the selected Columns from each tab to the 4th tab, so that I could have a better modification of my data. Each cloned column must has the same functionality as its "mother".
I've managed to have the columns that I select in my "end" tab, but The elements of it don't have the same functions and eventhandlers as the original ones. How can I make the cloned columns be the same with the original ones? Is that a right way of cloning columns that I used?
I've made a simple sample of my application, to show you its format. I'm writing code in C# and WPF.
Edited XAML:
<Window x:Class="WpfApp1.MainWindow"
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:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="500" Width="700">
<Grid>
<TabControl x:Name="tabControl">
<TabItem Header="Tab1">
<Grid x:Name="tab1">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<StackPanel x:Name="tab1stack1" Grid.Column="0">
<Label x:Name="lbl1" Content="Col1" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,0,0,10" />
<TextBox x:Name="txt1" Width="50" Margin="0,0,0,10" />
<Button x:Name="btn1" Content="Btn1" Width="50" Margin="0,0,0,10" />
<CheckBox x:Name="ckb1" Content="Col1" HorizontalAlignment="Center" Margin="0,0,0,10" />
</StackPanel>
<StackPanel x:Name="tab1stack2" Grid.Column="1">
<Label Content="Col2" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,0,0,10" />
<TextBox x:Name="txt2" Width="50" Margin="0,0,0,10" />
<Button Content="Btn2" Width="50" Margin="0,0,0,10" />
<CheckBox Content="Col2" HorizontalAlignment="Center" Margin="0,0,0,10" />
</StackPanel>
<Grid x:Name="ao1" Grid.Column="2">
<Label x:Name="aol1" Content="{Binding Path=Text, ElementName=aot1}" HorizontalAlignment="Center" Margin="0,2,0,0" VerticalAlignment="Top" MouseDoubleClick="aol1_MouseDoubleClick" ToolTip="Double-Click to rename, and press Enter to apply."/>
<TextBox x:Name="aot1" HorizontalAlignment="Center" Height="26" Margin="0,2,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Text="AnalogOut1 [Ch0]" KeyDown="aot1_KeyDown" Visibility="Hidden" LostFocus="aot1_LostFocus" />
<StackPanel Margin="0,30,0,0">
<StackPanel Orientation="Vertical" Margin="0,10,0,0" HorizontalAlignment="Left" >
<CheckBox x:Name="ao1enable" Content="Enable" Margin="0,0,0,10" HorizontalAlignment="Left" Padding="4,0,0,0" Unchecked="ao1enable_Unchecked" />
<CheckBox x:Name="ao1live" Content="Live" HorizontalAlignment="Left" Padding="4,0,0,0" />
</StackPanel>
<Button x:Name="ao1kickout" Content="Kickout" Margin="10" HorizontalAlignment="Center" Click="ao1kickout_Click" BorderBrush="Red" />
<Label x:Name="lb_amp1" Content="Amplitude:" HorizontalAlignment="Center" Margin="0,10,0,0" />
<StackPanel Orientation="Horizontal" Margin="0" HorizontalAlignment="Center">
<TextBox x:Name="txt_an_amp1" Width="50" Height="20" BorderThickness="1,1,0,1" VerticalContentAlignment="Center" HorizontalContentAlignment="Right" />
<Label Content="V" Width="25" BorderThickness="0,1,1,1" Margin="0" HorizontalAlignment="Right" Height="20" Padding="0" BorderBrush="#FFABADB3" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" />
</StackPanel>
<TextBlock x:Name="tb_no_an_amp1" Margin="5" FontSize="10" Foreground="Red" HorizontalAlignment="Center" />
<Label x:Name="WaveType1" Content="Wave Type:" HorizontalAlignment="Center" Margin="0,10,0,0" />
<ComboBox Margin="10,0" IsReadOnly="True" IsEditable="True" Text="Please select" HorizontalAlignment="Center" >
<ComboBoxItem x:Name="ao1wt1" Content="Sine" HorizontalAlignment="Left" Width="198" Selected="ao1wt1_Selected" />
<ComboBoxItem x:Name="ao1wt2" Content="Sawtooth" HorizontalAlignment="Left" Width="198" Selected="ao1wt2_Selected"/>
<ComboBoxItem x:Name="ao1wt3" Content="Triangle" HorizontalAlignment="Left" Width="198" Selected="ao1wt3_Selected"/>
<ComboBoxItem x:Name="ao1wt4" Content="DC Value" HorizontalAlignment="Left" Width="198" Selected="ao1wt4_Selected"/>
</ComboBox>
<Grid x:Name="Signal1Params" Margin="0,0,0,10" Visibility="Hidden" >
<StackPanel>
<Label x:Name="lb_ao1sp1" Content="Frequency:" Margin="0,5,0,0" HorizontalAlignment="Center" VerticalAlignment="Top" />
<StackPanel Orientation="Horizontal" Margin="0" HorizontalAlignment="Center">
<TextBox x:Name="txt_ao1sp1" Text="" Width="50" Height="20" BorderThickness="1,1,0,1" Margin="0,5,0,5" VerticalContentAlignment="Center" HorizontalContentAlignment="Right" />
<Label Content="Hz" Width="25" BorderThickness="0,1,1,1" Margin="0" HorizontalAlignment="Right" Height="20" Padding="0" BorderBrush="#FFABADB3" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" />
</StackPanel>
<TextBlock x:Name="tb_no_an_freq1" Margin="5,5,5,0" FontSize="10" Foreground="Red" HorizontalAlignment="Center" />
<Label x:Name="lb_ao1sp2" Content="Offset:" Margin="0,5,0,0" HorizontalAlignment="Center" VerticalAlignment="Top" />
<StackPanel x:Name="ao1sp2" Orientation="Horizontal" Margin="0" HorizontalAlignment="Center">
<TextBox x:Name="txt_ao1sp2" Text="" Width="50" Height="20" BorderThickness="1,1,0,1" Margin="0,5,0,5" VerticalContentAlignment="Center" HorizontalContentAlignment="Right" />
<Label Content="deg" Width="25" BorderThickness="0,1,1,1" Margin="0" HorizontalAlignment="Right" Height="20" Padding="0" BorderBrush="#FFABADB3" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" />
</StackPanel>
<TextBlock x:Name="tb_no_an_offset1" Margin="5,5,5,0" FontSize="10" Foreground="Red" HorizontalAlignment="Center" />
<Label x:Name="lb_ao1sp3" Content="Bias:" Margin="0,5,0,0" HorizontalAlignment="Center" VerticalAlignment="Top" />
<StackPanel Orientation="Horizontal" Margin="0" HorizontalAlignment="Center">
<TextBox x:Name="txt_ao1sp3" Text="" Width="50" Height="20" BorderThickness="1,1,0,1" Margin="0,5,0,5" VerticalContentAlignment="Center" HorizontalContentAlignment="Right" />
<Label Content="V" Width="25" BorderThickness="0,1,1,1" Margin="0" HorizontalAlignment="Right" Height="20" Padding="0" BorderBrush="#FFABADB3" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" />
</StackPanel>
<TextBlock x:Name="tb_no_an_bias1" Margin="5,5,5,0" FontSize="10" Foreground="Red" HorizontalAlignment="Center" />
<CheckBox x:Name="Signal_Period1" Content="One-Shot Period" HorizontalAlignment="Center" Margin="0,5,0,0" />
</StackPanel>
</Grid>
</StackPanel>
</Grid>
</Grid>
</TabItem>
<TabItem Header="Tab2">
<Grid x:Name="tab2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<ComboBox x:Name="cob_Add" Height="32" VerticalAlignment="Top" Width="150" HorizontalAlignment="Left" UseLayoutRounding="True" SelectedIndex="-1" Text="Add New Column" IsEditable="True" IsReadOnly="True" Margin="50,0,0,0">
<ComboBoxItem x:Name="cob_Add1" Selected="cob_Add1_Selected" Content="Column1" />
<ComboBoxItem x:Name="cob_Add2" Selected="cob_Add2_Selected" Content="Column2" />
<ComboBoxItem x:Name="cob_Add3" Selected="cob_Add3_Selected" Content="Column3" />
</ComboBox>
<ComboBox x:Name="cob_Remove" Height="32" VerticalAlignment="Top" Width="150" HorizontalAlignment="Right" UseLayoutRounding="True" SelectedIndex="-1" Text="Remove Column" IsEditable="True" IsReadOnly="True" Margin="0,0,50,0">
<ComboBoxItem x:Name="cob_Remove1" Selected="cob_Remove1_Selected" Content="Column1" />
<ComboBoxItem x:Name="cob_Remove2" Selected="cob_Remove2_Selected" Content="Column2" />
<ComboBoxItem x:Name="cob_Remove3" Selected="cob_Remove3_Selected" Content="Column3" />
</ComboBox>
<Grid x:Name="newcolumns" Grid.Row="1"/>
</Grid>
</TabItem>
</TabControl>
</Grid>
Edited Code Behind:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml;
namespace WpfApp1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public ObservableCollection<DataElement> MyList { get; set; }
public ObservableCollection<int> ComboBoxItems { get; set; }
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
this.ComboBoxItems = new ObservableCollection<int>() { 1, 2, 3 };
this.MyList = new ObservableCollection<DataElement>();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Button btn = sender as Button;
DataElement dataContext = btn.DataContext as DataElement;
//tab2.Background = Brushes.Red;// do something here <------
//btn.Click += btn1_Click;
}
//private void btn1_Click(object sender, RoutedEventArgs e)
//{
// tab2.Background = Brushes.Red;
//}
//private void btn2_Click(object sender, RoutedEventArgs e)
//{
// tab2.Background = Brushes.Green;
//}
private void cob_Add_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ComboBox cb = sender as ComboBox;
int? comboBoxItemDataContext = cb.SelectedItem as int?;
this.MyList.Add(new DataElement() { Label1 = "Output" + comboBoxItemDataContext.ToString(), Text1 = "", ButtonName = "btn" + comboBoxItemDataContext.ToString(), IsChecked = true });
}
private void aol1_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
//some code
}
private void aot1_KeyDown(object sender, KeyEventArgs e)
{
//some code
}
private void aot1_LostFocus(object sender, RoutedEventArgs e)
{
//some code
}
private void ao1enable_Unchecked(object sender, RoutedEventArgs e)
{
//some code
}
private void a1_init()
{
//some code
}
private void ao1kickout_Click(object sender, RoutedEventArgs e)
{
//if (ao1enable.IsChecked == true)
//{
// an1kick();
//}
}
private void an1kick()
{
//a1_init();
//some code
}
private void ao1wt1_Selected(object sender, RoutedEventArgs e)
{
//some code
}
private void ao1wt2_Selected(object sender, RoutedEventArgs e)
{
//some code
}
private void ao1wt3_Selected(object sender, RoutedEventArgs e)
{
//some code
}
private void ao1wt4_Selected(object sender, RoutedEventArgs e)
{
//some code
}
public class DataElement
{
public string Label1 { get; set; }
public string Text1 { get; set; }
public string ButtonName { get; set; }
public bool IsChecked { get; set; }
}
}
<Window x:Class="WpfApp1.MainWindow"
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:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TabControl x:Name="tabControl">
<TabItem Header="Tab2">
<Grid x:Name="tab2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<ComboBox
x:Name="comboBox"
Height="32"
VerticalAlignment="Top"
Width="150"
HorizontalAlignment="Left"
UseLayoutRounding="True"
SelectedIndex="-1"
Text="Add New Column"
IsEditable="True"
IsReadOnly="True"
Margin="50,0,0,0"
SelectionChanged="cob_Add_SelectionChanged"
ItemsSource="{Binding ComboBoxItems}"
/>
<ListBox Width="400" ItemsSource="{Binding MyList}" Grid.Row="1" x:Name="Test">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<Label Content="{Binding Label1}" />
<TextBox Text="{Binding Text1}" />
<Button Content="{Binding ButtonName}" Click="Button_Click"/>
<CheckBox IsChecked="{Binding IsChecked}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</TabItem>
</TabControl>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml;
namespace WpfApp1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public ObservableCollection<DataElement> MyList { get; set; }
public ObservableCollection<int> ComboBoxItems { get; set; }
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
this.ComboBoxItems = new ObservableCollection<int>() { 1, 2, 3 };
this.MyList = new ObservableCollection<DataElement>();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Button btn = sender as Button;
DataElement dataContext = btn.DataContext as DataElement;
// do something here <------
}
private void cob_Add_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ComboBox cb = sender as ComboBox;
int? comboBoxItemDataContext = cb.SelectedItem as int?;
if (comboBoxItemDataContext == 1)
{
this.MyList.Add(new DataElement() { Label1="1", Text1 = "1", ButtonName = "1", IsChecked = true });
}
if (comboBoxItemDataContext == 2)
{
this.MyList.Add(new DataElement() { Label1 = "2", Text1 = "2", ButtonName = "2", IsChecked = true });
}
if (comboBoxItemDataContext == 3)
{
this.MyList.Add(new DataElement() { Label1 = "3", Text1 = "3", ButtonName = "3", IsChecked = true });
}
}
}
public class DataElement
{
public string Label1 { get; set; }
public string Text1 { get; set; }
public string ButtonName { get; set; }
public bool IsChecked { get; set; }
}
}

Edit WPF listview item and commit changes

Updated
Link to code: Dropbox files
I have a WPF listview populated with a data which is bound through itemsSource. The item bound is a class object called User which contains a handful of properties such as Name, Age, Mail and Info.
What I want to do is be able to double click any listview item and popup an edit dialog which will allow me to change the Mail and Info of that individual. Those changes however will only be committed when i hit OK otherwise they are ignored.
The problem or place where I'm stuck at is, how do i populate the Edit Dialog with the selected listview item's info/mail?
How do i commit those changes back to the item and update the main listview? The rest of the code regarding the popup dialog and whatnot is all implemented already.
The Main Dialog:
XAML - Main Dialog
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="240" Width="350"
WindowStartupLocation="CenterScreen">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListView Name="lvDataBinding" Grid.Row="0" Background="LightBlue">
<ListView.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock Text="Name: " />
<TextBlock Text="{Binding Name}" FontWeight="Bold" />
<TextBlock Text=", " />
<TextBlock Text="Age: " />
<TextBlock Text="{Binding Age}" FontWeight="Bold" />
<TextBlock Text=" (" />
<TextBlock Text="{Binding Mail}" TextDecorations="Underline" Foreground="Blue" Cursor="Hand" />
<TextBlock Text=")" />
</WrapPanel>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<EventSetter Event="MouseDoubleClick" Handler="listViewItem_MouseDoubleClick" />
</Style>
</ListView.ItemContainerStyle>
</ListView>
<StackPanel Grid.Row="1" Orientation="Horizontal">
<Label Content="Selected:" HorizontalAlignment="Left"/>
<Label Content="{Binding SelectedItem.Info, ElementName=lvDataBinding}" HorizontalAlignment="Left" Width="140"/>
<!--<Label Content="{Binding ElementName=lvDataBinding, Path=SelectedItem.Name}" HorizontalAlignment="Left" Margin="72,172,0,0" Width="140"/>-->
</StackPanel>
</Grid>
</Window>
CS - Main Dialog
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
List<User> items = new List<User>();
items.Add(new User() { Name = "John Doe", Age = 42, Mail = "john#doe-family.com", Info = "A basketball player"});
items.Add(new User() { Name = "Jane Doe", Age = 39, Mail = "jane#doe-family.com", Info = "A soccer player" });
items.Add(new User() { Name = "Sammy Doe", Age = 13, Mail = "sammy.doe#gmail.com", Info = "A hockey player" });
lvDataBinding.ItemsSource = items;
}
private void listViewItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
ListViewItem item = sender as ListViewItem;
object obj = item.Content;
//User user = sender as User;
Console.WriteLine(item);
// popup window
Window editDialog = new EditWindow();
editDialog.Owner = this;
editDialog.ShowDialog();
if (editDialog.DialogResult.HasValue && editDialog.DialogResult.Value)
{
Console.WriteLine("User pressed OK");
;
}
else
{
Console.WriteLine("User pressed Cancel");
}
}
}
public class User
{
public string Name { get; set; }
public int Age { get; set; }
public string Mail { get; set; }
public string Info { get; set; }
}
}
The Edit Dialog:
XAML - Edit Dialog
<Window x:Class="WpfApplication1.EditWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="EditWindow" Height="140" Width="200"
WindowStartupLocation="CenterScreen">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Content="Email: " Grid.Row="0" Grid.Column="0"/>
<TextBox Background="AliceBlue" Grid.Row="0" Grid.Column="1" AcceptsReturn="True" TextWrapping="Wrap" DockPanel.Dock="Right"/>
<Label Content="Info: " Grid.Row="1" Grid.Column="0"/>
<TextBox Background="AliceBlue" Grid.Row="1" Grid.Column="1" AcceptsReturn="True" TextWrapping="Wrap" DockPanel.Dock="Right"/>
<StackPanel Grid.Row="2" Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Bottom">
<Button Content="Cancel" MinWidth="50" Height="25" Click="ButtonCancelClick"/>
<Button Content="OK" MinWidth="50" Height="25" Click="ButtonOkClick"/>
</StackPanel>
</Grid>
</Window>
CS - Edit Dialog
using System.Windows;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for EditWindow.xaml
/// </summary>
public partial class EditWindow : Window
{
public EditWindow()
{
InitializeComponent();
}
private void ButtonOkClick(object sender, RoutedEventArgs e)
{
DialogResult = true;
this.Close();
}
private void ButtonCancelClick(object sender, RoutedEventArgs e)
{
DialogResult = false;
this.Close();
}
}
}
There are many things to change in order to get this working.
Implement INotifyPropertyChanged on your User class
You cannot have two way binding in wPF without it. Just google and read till you understand how it works.
Create a public CurrentItem property on your EditWindow
(listViewItem_MouseDoubleClick event)
Create a new instance of User class (myUser) and copy all property values from item.Content (you first need to typecast this as a user object)
Set the new CurrentItem of editDialog.CurrentItem = myUser
if the user presses ok copy all properties of editDialog.CurrentItem back to item.Content object (remember this should be already typecasted to User)
Create all Bindins on EditWindow pointing to CurrentItem object.
Hope that helps.

MVVM datagrid doesn't display

Hi Learning MVVM and I am bit confused, I am trying to display my model name in a list and here what I have.
Model
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
namespace Morza.Model
{
public class DBEnvironment : INotifyPropertyChanged
{
private String _Name;
private String _HostName;
private String _HostPath;
public DBEnvironment(String __name, String __hostname, String __hostpath)
{
Name = __name;
HostName = __hostname;
HostPath = __hostpath;
}
public String Name {
get
{
return _Name;
}
set
{
_Name = value;
OnPropertyChanged("Name");
}
}
public String HostName
{
get
{
return _HostName;
}
set
{
_HostName = value;
OnPropertyChanged("HostName");
}
}
public String HostPath
{
get
{
return _HostPath;
}
set
{
_HostPath = value;
OnPropertyChanged("HostPath");
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
}
ModelView
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Morza.Model;
using System.Collections.ObjectModel;
namespace Morza.ViewModel
{
internal class LoginViewModel : ViewModelBase
{
ObservableCollection<DBEnvironment> _DBEnvironments;
private DBEnvironment _obj;
public LoginViewModel()
{
DBEnvironmentInfo = new ObservableCollection<DBEnvironment>();
DBEnvironmentInfo.Add(new DBEnvironment("T2", "127.0.0.1", "C:"));
DBEnvironmentInfo.Add(new DBEnvironment("T2", "127.0.0.1", "C:"));
DBEnvironmentInfo.Add(new DBEnvironment("T2", "127.0.0.1", "C:"));
DBEnvironmentInfo.Add(new DBEnvironment("T2", "127.0.0.1", "C:"));
}
public DBEnvironment DBEnvironment {
get
{
return _obj;
}
set
{
_obj = value;
}
}
public ObservableCollection<DBEnvironment> DBEnvironmentInfo
{
get
{
return _DBEnvironments;
}
set
{
_DBEnvironments = value;
OnPropertyChanged("PersonsInfo");
}
}
}
}
View
<Window x:Class="Morza.View.Login"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Login" Height="260" Width="425" WindowStartupLocation="CenterScreen" Background="LightBlue" ResizeMode="NoResize">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="10"></RowDefinition> <!-- 0 Nothing -->
<RowDefinition Height="25"></RowDefinition> <!-- 1 Label Instruction -->
<RowDefinition Height="10"></RowDefinition> <!-- 2 Nothing -->
<RowDefinition Height="25"></RowDefinition> <!-- 3 Username -->
<RowDefinition Height="10"></RowDefinition> <!-- 4 Nothing -->
<RowDefinition Height="25"></RowDefinition> <!-- 5 Password -->
<RowDefinition Height="10"></RowDefinition> <!-- 6 Nothing -->
<RowDefinition Height="25"></RowDefinition> <!-- 7 Environment -->
<RowDefinition Height="10"></RowDefinition> <!-- 8 Nothing -->
<RowDefinition Height="25"></RowDefinition> <!-- 9 Label Warning -->
<RowDefinition Height="10"></RowDefinition> <!-- 10 Nothing -->
<RowDefinition Height="25"></RowDefinition> <!-- 11 Button-->
<RowDefinition Height="10"></RowDefinition> <!-- 12 Nothing -->
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition Width="150"></ColumnDefinition>
<ColumnDefinition Width="25"></ColumnDefinition>
<ColumnDefinition Width="150"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Name="lblInstruction" Content="Enter a Username, Password, and Environment" Grid.Column="1" Grid.ColumnSpan="3" Grid.Row="1" HorizontalAlignment="Center"></Label>
<Label Name="lblUsername" Grid.Column="1" Grid.Row="3" Content="Username:" HorizontalAlignment="Right"></Label>
<TextBox Name="txtUsername" Grid.Column="3" Grid.Row="3"></TextBox>
<Label Name="lblPassword" Grid.Column="1" Grid.Row="5" Content="Password:" HorizontalAlignment="Right"></Label>
<PasswordBox Name="pwdPassword" Grid.Column="3" Grid.Row="5"></PasswordBox>
<Label Name="lblEnv" Grid.Column="1" Grid.Row="7" Content="Environment:" HorizontalAlignment="Right"></Label>
<ListView Grid.Column="1" Grid.ColumnSpan="3" Grid.Row="7" ItemsSource="{Binding DBEnvironmentInfo}" >
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<Label Content="{Binding DBEnvironmentInfo.Name}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Label Name="lblWarning" Content="" Grid.Column="1" Grid.ColumnSpan="3" Foreground="Red" Grid.Row="9" HorizontalAlignment="Center"></Label>
<Button Name="btnLogin" Content="Login" Grid.Column="1" Grid.Row="11"></Button>
<Button Name="btnCancel" Content="Exit" Grid.Column="3" Grid.Row="11" IsCancel="True"></Button>
</Grid>
</Window>
When running this code, the issue is the grid is blank. I am not using any framework that I am aware and don't really want to. If there something I am missing.
Looks like you forgot to set the DataContext of the Window:
<Window
...
xmlns:ViewModels="clr-namespace:Morza.ViewModel">
<Window.DataContext>
<ViewModels:LoginViewModel />
</Window.DataContext>
...
Also, another thing to mention is that you do not need to add the property name in your ListView DataTemplate:
<Label Content="{Binding Name}" />
This is because your DataTemplate is bound to a single object in the list.

Access DataTemplate Control At Run Time

I am Working on Windows phone 8.1.I Making Simple ListView Demo Which is Contain two Image And Two TextBlock.
<ListView x:Name="lst1" Grid.ColumnSpan="2" >
<ListView.ItemTemplate>
<DataTemplate >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Image x:Name="imgSender" Source="Assets/button_register.png" Stretch="None" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="8,15,8,8" />
<TextBlock Text="{Binding Sender}" FontSize="18" Foreground="Black" FontWeight="Bold" HorizontalAlignment="Center" Margin="0,12,0,0"/>
<Image x:Name="imgReceiver" Source="Assets/button_register.png" Grid.Row="1" Stretch="None" VerticalAlignment="Top" Margin="4,0" />
<TextBlock Text="{Binding Receiver}" FontSize="18" Foreground="Black" FontWeight="Bold" HorizontalAlignment="Center" Grid.Row="1" VerticalAlignment="Top"/>
<Image Source="Assets/scroll_line_addcategory.png" Grid.Row="2" Stretch="None" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="4,8,4,0" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
And My Problem is That I Want to Set the Visibility of 'imgSender' at Runtime in Xaml.cs File.
Is Anybuddy Have Any Idea For Access UI Control Contain by Data Template.
<ListView x:Name="lst1" Grid.ColumnSpan="2" >
<ListView.ItemTemplate>
<DataTemplate >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Image Visibility="{Binding SenderVisibility}" x:Name="imgSender" Source="Assets/button_register.png" Stretch="None" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="8,15,8,8" />
<TextBlock Text="{Binding Sender}" FontSize="18" Foreground="Black" FontWeight="Bold" HorizontalAlignment="Center" Margin="0,12,0,0"/>
<Image x:Name="imgReceiver" Source="Assets/button_register.png" Grid.Row="1" Stretch="None" VerticalAlignment="Top" Margin="4,0" />
<TextBlock Text="{Binding Receiver}" FontSize="18" Foreground="Black" FontWeight="Bold" HorizontalAlignment="Center" Grid.Row="1" VerticalAlignment="Top"/>
<Image Source="Assets/scroll_line_addcategory.png" Grid.Row="2" Stretch="None" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="4,8,4,0" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
And my Model Class is
public class User : INotifyPropertyChanged
{
private string sender = string.Empty;
private string receiver = string.Empty;
private string senderVisibility = string.Empty;
private string receiverVisibility = string.Empty;
public string Sender
{
get
{
return sender;
}
set
{
if (value != this.sender)
{
this.sender = value;
NotifyPropertyChanged("Sender");
}
}
}
public string Receiver
{
get
{
return this.receiver;
}
set
{
if (value != this.receiver)
{
this.receiver = value;
NotifyPropertyChanged("Receiver");
}
}
}
public string ReceiverVisibility
{
get
{
return this.receiverVisibility;
}
set
{
if (value != this.receiverVisibility)
{
this.receiverVisibility = value;
NotifyPropertyChanged("ReceiverVisibility");
}
}
}
public string SenderVisibility
{
get
{
return this.senderVisibility;
}
set
{
if (value != this.senderVisibility)
{
this.senderVisibility = value;
NotifyPropertyChanged("SenderVisibility");
}
}
}
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
If your ListView contains only one item you can easily subscribe to Loaded event of imgSender and then control it's Visibility.
private Image _imgSender;
void Image_Loaded(object sender, RoutedEventArgs e)
{
_imgSender = sender as Image();
}
void AnotherMethod()
{
if (_imgSender != null)
_imgSender.Visibility = Visibility.Collapsed;
}
EDIT
FOR MULTIPLE ITEMS
void HideImage(int elementIndex)
{
var container = lst1.ContainerFromIndex(elementIndex) as ListViewItem;
var imageSender = (container.Content as Grid).Children[0] as Image;
imageSender.Visibility = Visibility.Collapsed;
}
You can add a BooleanToVisibilityConverter
<Page.Resources>
<converter:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</Page.Resources>
<ListView x:Name="lst1" Grid.ColumnSpan="2"
ItemsSource="{Binding TelecomCollection}">
<ListView.ItemTemplate>
<DataTemplate >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Image x:Name="imgSender" Source="Assets/button_register.png" Stretch="None" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="8,15,8,8"
Visibility="{Binding ShowImgReceiver, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<TextBlock Text="{Binding Sender}" FontSize="18" Foreground="Black" FontWeight="Bold" HorizontalAlignment="Center" Margin="0,12,0,0"/>
<Image x:Name="imgReceiver" Source="Assets/button_register.png" Grid.Row="1" Stretch="None" VerticalAlignment="Top" Margin="4,0" />
<TextBlock Text="{Binding Receiver}" FontSize="18" Foreground="Black" FontWeight="Bold" HorizontalAlignment="Center" Grid.Row="1" VerticalAlignment="Top"/>
<Image Source="Assets/scroll_line_addcategory.png" Grid.Row="2" Stretch="None" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="4,8,4,0" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Then in your item class you can add ShowImgReceiver
public class Telecom
{
string Receiver {get; set;}
string Sender {get; set;}
bool ShowImgReceiver{get; set;}
}
In your binding class
public class ViewModel
{
public ObservableCollection<Telecom> TelecomCollection {get; set;}
}
If you want to make an item's image visibility Collapsed, then
TelecomCollection[0].ShowImgReceiver = false;
and to make it again Visible
TelecomCollection[0].ShowImgReceiver = true;

Categories

Resources