I am working on silverlight and I am new in it, I have a combox box,inside which I have a checkbox and textbox. I want to get the value of these controls on button click, How can I do this in SilverLight?
This is my ComboBox
<ComboBox x:Name="Type" VerticalAlignment="Top" Margin="2,8,-2,0" Grid.ColumnSpan="3" Height="28" Padding="3">
<ComboBoxItem>
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="*" MinWidth="105" />
<ColumnDefinition Width="60" />
</Grid.ColumnDefinitions>
<CheckBox IsChecked="true" VerticalAlignment="Center" Grid.Column="0"/>
<TextBlock Text="All" VerticalAlignment="Center" Grid.Column="1" Style="{x:Null}" FontSize="11"/>
</Grid>
</ComboBoxItem>
<ComboBoxItem>
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="*" MinWidth="105" />
<ColumnDefinition Width="60" />
</Grid.ColumnDefinitions>
<CheckBox IsChecked="true" VerticalAlignment="Center" Grid.Column="0"/>
<TextBlock Text="General" VerticalAlignment="Center" Grid.Column="1" Style="{x:Null}" FontSize="11"/>
<TextBox Text="25" VerticalAlignment="Center" Grid.Column="2" FontSize="11" Padding="2" HorizontalContentAlignment="Right"/>
</Grid>
</ComboBoxItem>
</ComboBox>
User have option to select multiple values
I am using MVVM pattern
Since all of your ComboBox Items are unchanging, you can give Names to those items and reference them directly.
<ComboBoxItem x:Name="ComboItemAll">
...
</ComboBoxItem>
<ComboBoxItem x:Name="ComboItemGeneral">
...
</ComboBoxItem>
and the in the Button Click event:
if (ComboItemAll.IsSelected)
{
...
}
else if (ComboItemGeneral.IsSelected)
{
...
}
alternatively, you could also get this information from your ComboBox "Type":
var selectedItem = Type.SelectedItem;
if (selectedItem.Name.StartsWith("ComboItemAll"))
{
...
}
else if (selectedItem.Name.StartsWith("ComboItemGeneral"))
{
...
}
For MVVM (Edit):
Xaml (View):
<ComboBox SelectedItem="{Binding SelectedCustomItem, Mode=TwoWay}" ItemsSource="{CustomItems}" ItemTemplate={StaticResource CustomItemsTemplate} />
Xaml (Resource):
<DataTemplate x:Key="CustomItemsTemplate">
<StackPanel
<CheckBox IsChecked="{Binding IsSelected}" VerticalAlignment="Center"/>
<TextBlock Text="{Binding CustomPropertyFromCustomClass}"/>
</StackPanel>
</DataTemplate>
VM:
public class ViewModel
{
public ViewModel()
{
CustomItems = new ObservableCollection<CustomClass>();
CustomItems.Add(new CustomClass() { "All" });
CustomItems.Add(new CustomClass() { "General" });
}
private ObservableCollection<CustomClass> customItems = null;
public ObservableCollection<CustomClass> CustomItems
{
get { return customItems; }
set
{
if (object.Equals(value, customItems) == false)
{
customItems = value;
OnPropertyChanged(() => CustomItems);
}
}
}
private CustomClass selectedCustomItem = null;
public CustomClass SelectedCustomItem
{
get { return selectedCustomItem; }
set
{
if (object.Equals(value, selectedCustomItem) == false)
{
selectedCustomItem= value;
OnPropertyChanged(() => SelectedCustomItem);
}
}
}
}
You should never reference your combobox directly from the ViewModel. Everything in your ViewModel should be related to data manipulation and know nothing of the View (aka ComboBox).
Everything else should be done in the view. If you need to access the ComboBox, you need you ask yourself why, and can I do that logic in the XAML through templates and bindings?
Related
I have create simple drag drop in WPF. In my application there are two Listviews. I have to drag list items from first listview and drop the item to second listview. I have created custom data template for first listview. When i drag the first listview item into second listview the data template is not customized so items are not displayed. How to display the list items with generic. Please help. My Code is as below,
<Grid Margin="0,20,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ListBox
Name="memberCollection"
Grid.Column="1"
Width="150"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
PreviewMouseLeftButtonDown="memberCollection_PreviewMouseLeftButtonDown">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBox Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Grid
Name="gridDrop"
Grid.Column="0"
Margin="20,0,0,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ListBox.Drop="grid_Drop"
ShowGridLines="True">
<ListBox
Grid.Row="0"
Grid.Column="0"
Margin="10,10,0,0"
AllowDrop="True" />
</Grid>
</Grid>
Code Behind
ObservableCollection<Member> member = new ObservableCollection<Member>();
public MainWindow()
{
InitializeComponent();
member.Add(new Member { Name = "Karthick", ID = "20011", Address = "10, MainRoad, Chennai" });
memberCollection.ItemsSource = member;
DataContext = new Member();
}
private void memberCollection_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
object selectedMember = memberCollection.SelectedItem as Member;
if (selectedMember != null)
DragDrop.DoDragDrop(memberCollection, selectedMember, DragDropEffects.All);
}
private void grid_Drop(object sender, RoutedEventArgs e)
{
ListBox listContent = e.Source as ListBox;
if (listContent != null)
Console.WriteLine("", Grid.GetColumn(listContent), Grid.GetRow(listContent));
DataObject item = (((DragEventArgs)e).Data) as DataObject;
object Target = ((Grid)(sender)).DataContext;
object listItem = item.GetData(Target.GetType());
if (listItem != null)
{
//listContent.Items.Add(listItem.Name.ToString());
//listContent.Items.Add(listItem.ID.ToString());
//listContent.Items.Add(listItem.Address.ToString());
//listContent.ItemTemplate = memberCollection.ItemTemplate;
listContent.Items.Add(listItem);
}
}
If you define the DataTemplate as a reusable resource, you can use it in both ListBoxes:
<Grid Margin="0,20,0,0">
<Grid.Resources>
<DataTemplate x:Key="dataTemplate">
<StackPanel>
<TextBox Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ListBox
Name="memberCollection"
Grid.Column="1"
Width="150"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
PreviewMouseLeftButtonDown="memberCollection_PreviewMouseLeftButtonDown"
ItemTemplate="{StaticResource dataTemplate}" />
<Grid
Name="gridDrop"
Grid.Column="0"
Margin="20,0,0,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ListBox.Drop="grid_Drop"
ShowGridLines="True">
<ListBox
Grid.Row="0"
Grid.Column="0"
Margin="10,10,0,0"
AllowDrop="True"
ItemTemplate="{StaticResource dataTemplate}"/>
</Grid>
</Grid>
If you want to display some other properties of the dropped Member in the second ListBox, you should define another ItemTemplate:
<ListBox
Grid.Row="0"
Grid.Column="0"
Margin="10,10,0,0"
AllowDrop="True">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding Id}" />
<TextBlock Tag="{Binding Address}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I have a data input form where i have textboxes,comboboxes and datepickers. I want to Bind comboboxes to the DB column so that users select the correct value for insertion. I have attached the viewmodel class and XAML code. In the viewmodel code "private void GetSW()" - this gets all the list of the entity class and "private void addSW()" this adds the record to the DB, Except the combobox binding everything works fine. in XAML i have binded combobox like this but this give blank combobox, please help what i am missing. I researched many topics on this forum but didn't find any solution
<ComboBox x:Name="PSW" Grid.Column="3" Grid.Row="2" ItemsSource="{Binding newSW.PreviousSW}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Height="20"/>
Its a ViewModel Code
using BusinessEntities;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using MUDB.Services;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace MUDB.Ui.Logic
{
public class SoftwareVersionListViewModel:ViewModelBase
{
private bool enableRowDetails=false;
public bool EnagleRowDetails
{
get { return enableRowDetails; }
set {
enableRowDetails = value;
RaisePropertyChanged();
}
}
public SoftwareVersionListViewModel()
{
SaveSW = new RelayCommand(addSW);
//savecommand = new RelayCommand(addprod);
GetSW();
newSW = new SoftwareDefEntity();
EditSW = new RelayCommand(() => {
EnagleRowDetails = true;
MessageBox.Show("Edit button clicked!!");});
//SWList = new SoftwareDefEntity(); //Initializing the object of the Entity class
}
public List<SoftwareDefEntity> SWentities
{
get;
set;
}
private SoftwareDefEntity _selectedsw;
public SoftwareDefEntity Selectedsw
{
get { return _selectedsw; }
set
{
_selectedsw = value; //This will get all the values of that particular Selected row that are defined in the entity class
EnagleRowDetails = false; //Reset boolean value EnagleRowDetails, so that the selected rowdetails are disabled until Edit button is not clicked.
//ShowView();
}
}
public RelayCommand SaveSW { get; private set; }
public RelayCommand EditSW { get; private set; }
public SoftwareDefEntity newSW { get; private set; }
private void ShowView()
{
//cUSTOM METHODS
}
private void GetSW() // Method that reads the data from the service layer
{
SWDefService obj = new SWDefService();
SWentities = obj.getSW() ; //getSW is the method refered in Service layer
}
private void addSW()
{
SWDefService obj = new SWDefService();
obj.addSW(newSW); //newproduct object will hold the value of the binded control, in XAML its binded like this "{Binding newproduct.ProductName(ProductName is the field name in the entityclass/DB table)}"
newSW = new SoftwareDefEntity();
}
}
}
This is the XAML Code
<UserControl x:Class="MUDB.Ui.CreateSW"
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:MUDB.Ui"
xmlns:converter="clr-namespace:MUDB.Ui.Logic.Converters;assembly=MUDB.Ui.Logic"
xmlns:enums="clr-namespace:MUDB.Ui.Logic.Enums;assembly=MUDB.Ui.Logic"
mc:Ignorable="d" Height="Auto" Width="Auto"
DataContext="{Binding SoftwareVersionList,Source={StaticResource Locator}}" >
<UserControl.Resources>
<converter:RadioButtonToBooleanConverter x:Key="RadioButtonToBooleanConverter" />
</UserControl.Resources>
<Grid>
<Border Background="#90000000" Visibility="{Binding Visibility}">
<Border BorderBrush="Black" BorderThickness="1" Background="White"
CornerRadius="10,0,10,0" VerticalAlignment="Center"
HorizontalAlignment="Center">
<Border.BitmapEffect>
<DropShadowBitmapEffect Color="Black" Opacity="0.5" Direction="270" ShadowDepth="0.7" />
</Border.BitmapEffect>
<Grid Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="25"/>
<RowDefinition Height="30"/>
<RowDefinition Height="25"/>
<RowDefinition Height="30"/>
<RowDefinition Height="25"/>
<RowDefinition Height="30"/>
<RowDefinition Height="100"/>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<Label Content="Create New Software Version" Grid.Column="0" Grid.Row="0" Foreground="White" Background="black"
HorizontalAlignment="Stretch" VerticalAlignment="Center" Grid.ColumnSpan="3" />
<Label Content="ECU" Grid.Column="0" Grid.Row="1" Foreground="Black" HorizontalAlignment="Left"
VerticalAlignment="Bottom" />
<Label Content="Software Name" Grid.Column="1" Grid.Row="1" Foreground="Black" HorizontalAlignment="Left"
VerticalAlignment="Bottom" />
<Label Content="Previous Software" Grid.Column="2" Grid.Row="1" Foreground="Black" HorizontalAlignment="Left"
VerticalAlignment="Bottom" />
<Label Content="Request Freeze Date" Grid.Column="0" Grid.Row="3" Foreground="Black" HorizontalAlignment="Left"
VerticalAlignment="Bottom" />
<Label Content="Request Freeze Status" Grid.Column="1" Grid.Row="3" Foreground="Black" HorizontalAlignment="Left"
VerticalAlignment="Bottom" />
<Label Content="Software Freeze Date" Grid.Column="0" Grid.Row="5" Foreground="Black" HorizontalAlignment="Left"
VerticalAlignment="Center" />
<Label Content="Software Freeze Status" Grid.Column="1" Grid.Row="5" Foreground="Black" HorizontalAlignment="Left"
VerticalAlignment="Center" />
<Label Content="Comments" Grid.Column="0" Grid.Row="7" Foreground="Black" HorizontalAlignment="Left"
VerticalAlignment="Center" />
<ComboBox x:Name="ECU" Grid.Column="0" Grid.Row="2" Text="{Binding newSW.ECU}" Margin="10 0 0 0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="80" Height="Auto">
<ComboBoxItem Name="cbi1">ACM</ComboBoxItem>
<ComboBoxItem Name="cbi2">MCM</ComboBoxItem>
</ComboBox>
<TextBox x:Name="SW" Grid.Column="1" Grid.Row="2" Text="{Binding newSW.SoftwareName}" HorizontalAlignment="Left" VerticalAlignment="Top" Height="Auto" Width="150" />
<ComboBox x:Name="PSW" Grid.Column="3" Grid.Row="2" ItemsSource="{Binding PreviousSW}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Height="20"/>
<DatePicker Grid.Column="0" Grid.Row="4" Margin="10 0 0 0" HorizontalAlignment="Left" VerticalAlignment="top" SelectedDate="{Binding newSW.Req_Freeze_Date}" Height="Auto" Width="Auto"/>
<DatePicker Grid.Column="0" Grid.Row="6" Margin="10 0 0 0" HorizontalAlignment="Left" VerticalAlignment="top" SelectedDate="{Binding newSW.SW_Freeze_Date}" Height="Auto" Width="Auto"/>
<RadioButton Content="Yes" GroupName="ReQstat" IsChecked="{Binding newSW.Req_Freeze_Status, Mode=OneWayToSource, Converter={StaticResource RadioButtonToBooleanConverter}, ConverterParameter={x:Static enums:RadioSelectionEnum.Yes}}" Style="{StaticResource AccentRadioButton}" Grid.Column="1" Grid.Row="4" HorizontalAlignment="Left" VerticalAlignment="Top" Height="14" Width="Auto"/>
<RadioButton Content="No" GroupName="ReQstat" IsChecked="{Binding newSW.Req_Freeze_Status, Mode=OneWayToSource, Converter={StaticResource RadioButtonToBooleanConverter}, ConverterParameter={x:Static enums:RadioSelectionEnum.No}}" Style="{StaticResource AccentRadioButton}" Grid.Column="1" Grid.Row="4" Margin="60 0 0 0" HorizontalAlignment="Left" VerticalAlignment="Top" Height="Auto" Width="Auto"/>
<RadioButton Content="Yes" GroupName="SWstat" IsChecked="{Binding newSW.SW_Freeze_Status, Mode=OneWayToSource, Converter={StaticResource RadioButtonToBooleanConverter}, ConverterParameter={x:Static enums:RadioSelectionEnum.Yes}}" Style="{StaticResource AccentRadioButton}" Grid.Column="1" Grid.Row="6" HorizontalAlignment="Left" VerticalAlignment="Top" Height="Auto" Width="Auto"/>
<RadioButton Content="No" GroupName="SWstat" IsChecked="{Binding newSW.SW_Freeze_Status, Mode=OneWayToSource, Converter={StaticResource RadioButtonToBooleanConverter}, ConverterParameter={x:Static enums:RadioSelectionEnum.No}}" Style="{StaticResource AccentRadioButton}" Grid.Column="1" Grid.Row="6" Margin="60 0 0 0" HorizontalAlignment="Left" VerticalAlignment="Top" Height="Auto" Width="Auto"/>
<TextBox x:Name="CommenttextBox" Grid.Column="1" Grid.Row="7" HorizontalAlignment="Left" Height="69" TextWrapping="WrapWithOverflow" VerticalAlignment="Center" Text="{Binding Comment}" Width="170" Margin="4.4,2.2,0,0" />
<UniformGrid Grid.Row="9" Margin="2" Columns="2" HorizontalAlignment="Stretch"
VerticalAlignment="Center" Height="Auto">
<Button x:Name="SaveButton" Command="{Binding SaveSW}" Content="Save" Height="27" />
<Button x:Name="CloseButton" Click="CloseButton_Click" Content="Close" Height="26" />
</UniformGrid>
</Grid>
</Border>
</Border>
</Grid>
</UserControl>
I guess you want to display the list of SoftwareDefEntity objects in your ComboBox.
Bind to the SWentities property then:
<ComboBox x:Name="PSW" Grid.Column="3" Grid.Row="2" ItemsSource="{Binding SWentities}" DisplayMemberPath="Name" ... />
And raise the PropertyChanged event in its setter of this property:
private List<SoftwareDefEntity> _swEntities;
public List<SoftwareDefEntity> SWentities
{
get { return _swEntities; }
set { _swEntities = value; RaisePropertyChanged(); }
}
This is the code to bind the data to combobox. i did not add any of other controls since those are working fine at your place. Observable collection is easy way to bind combobox .
Here is your View Model..
public class SoftwareVersionListViewModel : ViewModelBase
{
public SoftwareVersionListViewModel()
{
GetSW();
}
//Define the observable collection
private ObservableCollection<SoftwareDefEntity> _SWmappings2 = new ObservableCollection<SoftwareDefEntity>();
//here is your Entity list
public List<SoftwareDefEntity> SWentities
{
get;
set;
}
// Obeservable collection property for access
public ObservableCollection<SoftwareDefEntity> SWmappings2
{
get { return _SWmappings2; }
set
{
_SWmappings2 = value;
OnPropertyChanged("appeventmappings2");
}
}
/// <summary>
/// load the combobox
/// </summary>
private void GetSW() // Method that reads the data from the service layer
{
SWDefService obj = new SWDefService();
SWentities = obj.getSW(); //getSW is the method refered in Service layer
SWentities.ForEach(_SWmappings2.Add);
}
}
and Xaml...
<ComboBox x:Name="ComboBox" ItemsSource="{Binding SWmappings2, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="PreviousSW" SelectedItem="{Binding PreviousSW, Mode=TwoWay}" Grid.Row="0" >
</ComboBox>
I have a ListBox with Questions and Answers which is taking data from Database. Now i want to display or edit data from selected row from 'Listbox', but i have problem how to get to this row.
Edit. Image to show what i want to do:
http://imgur.com/5NHjYA4
My View:
<Window x:Class="QuizMaker.MainWindow"
<Window.DataContext>
<local:MainViewModel />
</Window.DataContext>
<Window.Resources>
<DataTemplate x:Key="QuestionsTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="320" />
<ColumnDefinition Width="120" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Path=Question}" FontWeight="Bold" />
<TextBlock Grid.Column="1" Text="{Binding Path=AnswerA}" />
<TextBlock Grid.Column="2" Text="{Binding Path=AnswerB}"/>
<TextBlock Grid.Column="3" Text="{Binding Path=AnswerC}"/>
<TextBlock Grid.Column="4" Text="{Binding Path=AnswerD}"/>
<TextBlock Grid.Column="5" Text="{Binding Path=RightAnswer}" FontWeight="Bold"/>
</Grid>
</DataTemplate>
</Window.Resources>
<Grid>
<ListBox DataContext="{Binding MyDataSet}"
x:Name="listBox"
ItemsSource="{Binding Path=QuestionTable}"
ItemTemplate="{StaticResource QuestionsTemplate}"
SelectedItem="{Binding SelectedItemString}"
/>
</Grid>
</Window>
And ViewModel(I cut most of properties)
{
class MainViewModel
{
private string _appPath;
private MainModel _MainModel;
public MainViewModel()
{
_MainModel = new MainModel();
mdbFile = Path.Combine(AppDataPath, "QuestionBase.mdb");
connString = $"Provider=Microsoft.Jet.OLEDB.4.0; Data Source={mdbFile}";
conn = new OleDbConnection(connString);
adapter = new OleDbDataAdapter("SELECT * FROM QuestionTable;", conn);
MyDataSet = new DataSet();
adapter.Fill(MyDataSet, "QuestionTable");
}
private void AddToDB()
{
conn.Open();
OleDbCommand myCommand = new OleDbCommand("Insert INTO QuestionTable ( Question, AnswerA, AnswerB, AnswerC, AnswerD ) Values(#Question, #AnswerA, #AnswerB, #AnswerC, #AnswerD)", conn);
myCommand.Parameters.Add("#Question", OleDbType.BSTR).Value = Question;
myCommand.Parameters.Add("#Question", OleDbType.BSTR).Value = AnswerA;
myCommand.Parameters.Add("#Question", OleDbType.BSTR).Value = AnswerB;
myCommand.Parameters.Add("#Question", OleDbType.BSTR).Value = AnswerC;
myCommand.Parameters.Add("#Question", OleDbType.BSTR).Value = AnswerD;
myCommand.ExecuteNonQuery();
conn.Close();
}
private string AppDataPath
{
get
{
if (string.IsNullOrEmpty(_appPath))
{
_appPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
}
return _appPath;
}
}
public OleDbDataAdapter adapter
{
get
{
return _MainModel.adapter;
}
set
{
_MainModel.adapter = value;
OnPropertyChanged("adapter");
}
}
public DataSet MyDataSet
{
get
{
return _MainModel.MyDataSet;
}
set
{
_MainModel.MyDataSet = value;
OnPropertyChanged("MyDataSet");
}
}
public string SelectedItemString
{
get
{
return _MainModel.SelectedItemString;
}
set
{
_MainModel.SelectedItemString = value;
OnPropertyChanged("SelectedItemString");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
Sorry I couldn't add a comment. I hope your requirement is to show the selected item's value in the TextBox and update the same value into your collection(in your case DataTable) as you change value from the TextBox. If that is your requirement change your TextBox bindings like this
<TextBox x:Name="ValueText" Text="{Binding SelectedItem.ColumnName, ElementName=listBox, UpdateSourceTrigger=PropertyChanged}" />
I don't know why you are binding SelectedItem to string type SelectedItemString property. It will create binding error as per your source.
Change your SelectedItemString property to a DataRow, and bind your other controls to that.
For example,
public DataRow SelectedItem
{
get
{
return _MainModel.SelectedItem;
}
set
{
_MainModel.SelectedItem = value;
OnPropertyChanged("SelectedItem");
}
}
And in XAML should be something like this :
<Window x:Class="QuizMaker.MainWindow"
<Window.DataContext>
<local:MainViewModel />
</Window.DataContext>
<Window.Resources>
<DataTemplate x:Key="QuestionsTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="320" />
<ColumnDefinition Width="120" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Path=Question}" FontWeight="Bold" />
<TextBlock Grid.Column="1" Text="{Binding Path=AnswerA}" />
<TextBlock Grid.Column="2" Text="{Binding Path=AnswerB}"/>
<TextBlock Grid.Column="3" Text="{Binding Path=AnswerC}"/>
<TextBlock Grid.Column="4" Text="{Binding Path=AnswerD}"/>
<TextBlock Grid.Column="5" Text="{Binding Path=RightAnswer}" FontWeight="Bold"/>
</Grid>
</DataTemplate>
</Window.Resources>
<DockPanel>
<ContentControl Content="{Binding SelectedItem}"
ContentTemplate="{StaticResource QuestionsTemplate}"
DockPanel.Dock="Top" />
<ListBox DataContext="{Binding MyDataSet}"
x:Name="listBox"
ItemsSource="{Binding Path=QuestionTable}"
ItemTemplate="{StaticResource QuestionsTemplate}"
SelectedItem="{Binding SelectedItem}"
/>
</DockPanel>
</Window>
Also if you really don't want to change the way you track your selected item, you could also bind directly to listBox.SelectedItem like Davys said
<ContentControl Content="{Binding ElementName=listBox, Path=SelectedItem}"
ContentTemplate="{StaticResource QuestionsTemplate}"
DockPanel.Dock="Top" />
I have this List box:
Here is the Code for my ListBox:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox x:Name="List" Grid.Row="0" ItemsSource="{Binding ShoppingItems}" FontSize="42" FontWeight="Light" FontFamily="Segoe WP Light" HorizontalContentAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Visible">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0" Margin="0,-15,0,22">
<Checkbox x:Name="MyCheckBox" IsChecked="{Binding IsChecked,Mode=TwoWay}"/>
</Grid>
<Grid x:Name="MyGrid" Margin="0,-15,0,22" Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding DisplayingItem}" FontSize="46" Grid.Column="0" Grid.Row="0" TextWrapping="Wrap" />
<TextBlock Text="quantity" FontSize="32" Grid.Row="1" Margin="6,0,0,0" Grid.Column="0" TextWrapping="Wrap"/>
<TextBlock Text="{Binding DisplayingQuantity}" FontSize="32" Grid.Column="1" Grid.Row="1" Margin="32,0,12,12" TextWrapping="Wrap"/>
<TextBlock Grid.Column="2" Grid.Row="1" FontSize="32" Margin="32,0,12,12" Text="{Binding DisplayingPackaging}" TextWrapping="Wrap"/>
<TextBlock Text="price" Margin="6,0,0,0" FontSize="32" Grid.Row="2" Grid.Column="0" TextWrapping="Wrap"/>
<TextBlock Text="$" FontSize="32" Grid.Row="2" Grid.Column="1" Margin="32,0,12,12" TextWrapping="Wrap"/>
<TextBlock Grid.Column="3" FontSize="32" Grid.Row="2" Margin="32,0,12,12" Text="{Binding DisplayingPrice}" TextWrapping="Wrap"/>
</Grid>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
it has a checkbox inside, the ListBox is populated by data from a SQLite db. I want when I check the Checkbox to receive a message showing me the name of the SelectedItem of the ListBox.
Here is the Property for my CheckBox
private bool isChecked;
public bool IsChecked
{
get
{
if(this.SelectedItem != null)
{
return this.selectedItem.IsChecked;
}
return false;
}
set
{
this.isChecked = value;
}
}
When I check my Checkbox and Click This Button:
private void CheckedItem(object p)
{
if (this.IsChecked != false)
{
MessageBox.Show("Checked");
}
}
Nothing Happens.
I have included my Checkbox in my SelectedItem Like this:
private ShowingModel selectedItem;
public ShowingModel SelectedItem
{
get
{
return selectedItem;
}
set
{
if(this.selectedItem != value)
{
this.selectedItem = value;
if (this.selectedItem != null)
{
this.product = selectedItem.DisplayingItem;
this.price = selectedItem.DisplayingPrice;
this.qty = selectedItem.DisplayingQuantity;
this.package = selectedItem.DisplayingPackaging;
this.isChecked = selectedItem.IsChecked;
}
RaisePropertyChanged("MyPackage");
RaisePropertyChanged("MyPrice");
RaisePropertyChanged("MyProduct");
RaisePropertyChanged("MyQty");
RaisePropertyChanged("IsChecked");
}
}
}
So Where is the Problem.
Not an answer but too much for a comment
This is just messed up
You need to read up on data binding and start over
The following get and set don't refer to the same value
private bool isChecked;
public bool IsChecked
{
get
{
if(this.SelectedItem != null)
{
return this.selectedItem.IsChecked;
}
return false;
}
set
{
this.isChecked = value;
}
}
No indication SelectedItem is bound to anything
On CheckedItem that is not the signature of an event handler
Like #Blam said your immediate problem is resolveable by actually setting an event handler for the CheckBox "MyCheckBox."
<CheckBox x:Name="MyCheckBox" IsChecked="{Binding IsChecked,Mode=TwoWay}"
Checked="MyCheckBox_Checked"/>
private void MyCheckBox_Checked(object sender, RoutedEventArgs e)
{
MessageBox.Show("Checked");
}
2 other things:
If you keep the property public ShowingModel SelectedItem, then I would move the RaisePropertyChanged inside of the if statement. Better yet, make each of the variables you're setting their own property like:
double MyPrice
{
get {return price;}
set { if(price >= 0.0)/* Don't want a negative price. \m/*/
{ price = value; RaisePropertyChanged("MyPrice"); } }
}
If you have it this way for deleting an item, then I would suggest making that clearer for future reference.
I would highly suggest you take a look at few other resources:
Databinding a listbox to an ObservableCollection in code. <-- The question was correct, and has the best way to do this.
Databinding a listbox to an ObservableCollection in XAML.
WPF Tutorial | DataTemplates.
Making the list item check the checkbox.
I am working on a WPF app where I need to dynamically create GroupBoxes(which contains combobxes, sliders and togglebutton) based on Button Click. I have two xaml files in my View Folder. 'CodecView.xaml' and 'CodecWidgetView.xaml'.
CodecView.XAML:
<Grid>
<ScrollViewer Name="GroupBoxScroll" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0" >
<Grid Name="NumberofCodecs" Style="{DynamicResource styleBackground}" />
</ScrollViewer>
</Grid>
<Button Content="Add Box" Name="AddBoxBtn" Command="{Binding AddGroupBoxCommand}" />
CodecWidgetView.xaml:
<GroupBox Header="{Binding GroupBoxHeader}" Height="Auto" HorizontalAlignment="Stretch" Margin="5,5,0,0" Name="groupBox1" VerticalAlignment="Stretch" Width="Auto">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ToggleButton Name="FrequencyBox" Content="Master" Grid.Column="1" Height="25" Width="50" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0" />
<ComboBox Grid.Column="2" Height="23" HorizontalAlignment="Center" Margin="0,0,0,0" Name="comboBox2" VerticalAlignment="Center" Width="80" />
<ComboBox Grid.Column="0" Height="23" HorizontalAlignment="Center" Margin="0,0,0,0" Name="comboBox1" VerticalAlignment="Center" Width="80" />
</Grid>
s
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ToggleButton Name="OneSixBit" Content="16 Bit" Grid.Column="0" Height="25" Width="45" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0" />
<ToggleButton Name="ThreeTwoBit" Content="32 Bit" Grid.Column="3" Height="25" Width="45" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0" />
<ToggleButton Name="TwentyBit" Content="20 Bit" Grid.Column="1" Height="25" Width="45" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0" />
<ToggleButton Name="TwentyFourBit" Content="24 Bit" Grid.Column="2" Height="25" Width="45" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0" />
</Grid>
<Grid Grid.Row="2">
<Label Name="BitDelay" Content="Bit Delay" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,205,0" Height="25" Width="55" />
<Slider Height="23" HorizontalAlignment="Center" Minimum="0.0" Maximum="255.0" TickFrequency="1.0" Margin="95,0,0,0" Name="bitdelayslider" VerticalAlignment="Center" Width="160" />
<TextBox Name="BitDelayValue" IsReadOnly="True" Text="{Binding ElementName=bitdelayslider,Path=Value}" Width="40" Height="20" Margin="0,0,110,0" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
<Grid Grid.Row="3">
<Label Name="DBGain" Content="DB Gain" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,205,0" Height="25" Width="55" />
<TextBox Name="DBGainValue" IsReadOnly="True" Text="{Binding ElementName=dbgainslider,Path=Value}" Width="40" Height="20" Margin="0,0,110,0" HorizontalAlignment="Center" VerticalAlignment="Center" />
<Slider Height="23" HorizontalAlignment="Center" Minimum="0.0" Maximum="59.5" TickFrequency="0.5" Margin="95,0,0,0" Name="dbgainslider" VerticalAlignment="Center" Width="160" />
</Grid>
</Grid>
</GroupBox>
CodecViewModel: Is a view model of CodecView.xaml
/// <summary>
/// Event for Refresh Button
/// </summary>
private ICommand mAddGroupBoxCommand;
public ICommand AddGroupBoxCommand
{
get
{
if (mAddGroupBoxCommand == null)
mAddGroupBoxCommand = new DelegateCommand(new Action(mAddGroupBoxCommandExecuted), new Func<bool>(mAddGroupBoxCommandCanExecute));
return mAddGroupBoxCommand;
}
set
{
mAddGroupBoxCommand = value;
}
}
public bool mAddGroupBoxCommandCanExecute()
{
return true;
}
public void mAddGroupBoxCommandExecuted()
{
//Here It should display the groupbox 4 times
}
ModelClass:
private string GroupBoxHeaderName;
public string GroupBoxHeader
{
get
{
return GroupBoxHeaderName;
}
set
{
GroupBoxHeaderName = value;
OnPropertyChanged("GroupBoxHeader");
}
}
Thus I want to add this Groupbox present in CodecWidgetView.xaml to my grid(NumberofCodecs) in CodecView.xaml on startup. And when I click the AddBoxButton it should dynamically generate the groupbox 4 times and display it :)
Now this is tricky, each Groupbox Header must display different names in every dynamically generated groupbox. Lets say on startup, 2 groupboxes are already displayed with Groupbox Header = "Location 1" and GroupBox Header = "Location 2". On AddgroupBox button click I want to have 4 groupboxes with Header as Groupbox Header = "Location 3" Groupbox Header = "Location 4" Groupbox Header = "Location 5" Groupbox Header = "Location 6".
Is it possible? :)
In the following code i am taking a itemscontrol in "CodecView.xaml" and for that itemscontrol ItemTemplate is your "CodecWidgetView.Xaml" and added description to that datatemplate. i have created another class CodecWidgetViewModel.cs which will be view model for "CodecWidgetView" view.
In the constructor of "CodecViewModel" i am creating instance for "CodecWidgetViewModel" and adding them to observable collection which is source of ItemsControl in the "CodecView"..
so at this point it will generate 2 CodecWidgetViews.. on button click i am adding 4 more instances so it will generate 4 CodecWidgetViews.. You can modify the code in the "mAddGroupBoxCommandExecuted" method as per your requirement..
on Button click
CodecView.XAML
<UserControl>
<UserControl.Resources>
<DataTemplate x:Key="CWDataTemplate">
<StackPanel>
<TextBlock Text="{Binding Description}"/>
<local:CodecWidgetView/>
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<Grid>
<Grid>
<ScrollViewer Name="GroupBoxScroll" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0" >
<Grid Name="NumberofCodecs" Style="{DynamicResource styleBackground}" >
<ItemsControl ItemTemplate="{StaticResource CWDataTemplate}" ItemsSource="{Binding CodecWidgets}"/>
</Grid>
</ScrollViewer>
</Grid>
<Button Content="Add Box" Name="AddBoxBtn" Command="{Binding AddGroupBoxCommand}" Click="AddBoxBtn_Click" HorizontalAlignment="Right" VerticalAlignment="Bottom" />
</Grid>
</UserControl>
CodecViewModel.cs
Create a property like this
public ObservableCollection<CodecWidgetViewModel> CodecWidgets { get; set; }
And add following code to your CodecViewModel constructor
CodecWidgets = new ObservableCollection<CodecWidgetViewModel>();
CodecWidgets.Add(new CodecWidgetViewModel { Description = "Location 1"});
CodecWidgets.Add(new CodecWidgetViewModel { Description = "Location 2" });
To Add widgets
public void mAddGroupBoxCommandExecuted()
{
CodecWidgets.Add(new CodecWidgetViewModel { Description = "Location 3" });
CodecWidgets.Add(new CodecWidgetViewModel { Description = "Location 4" });
CodecWidgets.Add(new CodecWidgetViewModel { Description = "Location 5" });
CodecWidgets.Add(new CodecWidgetViewModel { Description = "Location 6" });
}
Create following class
CodecWidgetViewModel.cs
public class CodecWidgetViewModel
{
private string _description;
public string Description {
get { return _description; }
set {
_description = value;
}
}
}