I am working on set of radiobuttons which are dynamicaly generated in my app. I seem to be facing a issue when it comes to access the class members. Here is what I have done till now:
XAML:
<GroupBox Header="Daughter Cards" Height="Auto" HorizontalAlignment="Stretch" Margin="20,5,20,20" Name="groupBox2" VerticalAlignment="Stretch" Width="Auto">
<Grid>
<Grid Grid.Column="0">
<ItemsControl ItemsSource="{Binding SlotChildren}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="3" Rows="8" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<RadioButton Content="{Binding SlotButtons}" Margin="0,10,0,0" IsChecked="{Binding IsChecked}" GroupName="SlotGroup" Height="15" Width="80" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
<Grid Grid.Column="1">
<ComboBox Grid.Row="0" ItemsSource="{Binding DaughterBoardBoxList}" SelectedItem="{Binding SelectedDaughterBoardBoxList, Mode=TwoWay}" SelectedIndex="0" Height="23" HorizontalAlignment="Center" Margin="0" Name="comboBox5" VerticalAlignment="Center" Width="158" />
<ComboBox Grid.Row="1" ItemsSource="{Binding DaughterVersionBoxList}" SelectedItem="{Binding SelectedDaughterVersionBoxList, Mode=TwoWay}" SelectedIndex="0" Height="23" HorizontalAlignment="Center" Margin="0" Name="comboBox6" VerticalAlignment="Center" Width="158" />
<ComboBox Grid.Row="2" ItemsSource="{Binding DaughterSerialBoxList}" SelectedItem="{Binding SelectedDaughterSerialBoxList, Mode=TwoWay}" SelectedIndex="0" Height="23" HorizontalAlignment="Center" Margin="0" Name="comboBox7" VerticalAlignment="Center" Width="158" />
<Button Grid.Row="1" Command="{Binding GetStringCommand}" Content="Get String" Height="23" HorizontalAlignment="Center" Margin="0" Name="RefreshDaughterCards" VerticalAlignment="Center" Width="90" />
<Button Grid.Row="2" Command="{Binding SetStringCommand}" Content="Set String" Height="23" HorizontalAlignment="Center" Margin="0" Name="WriteEEPROMDCBtn" VerticalAlignment="Center" Width="90" />
<Label Content="{Binding DaughterStatus}" Height="25" HorizontalAlignment="Center" Margin="0" Name="DaughterCardLabel" VerticalAlignment="Center" Width="170" />
</Grid>
</Grid>
</GroupBox>
EEPROMViewModel Class:
public ObservableCollection<EEPROMSlotViewModel> SlotChildren { get; set; }
public EEPROMViewModel ()
{
SlotChildren = new ObservableCollection<EEPROMSlotViewModel>();
SlotChildren.Add(new EEPROMSlotViewModel() { ParentVM = this, SlotButtons = "0 : None", ID = 0 });
SlotChildren.Add(new EEPROMSlotViewModel() { ParentVM = this, SlotButtons = "1 : None", ID = 1 });
SlotChildren.Add(new EEPROMSlotViewModel() { ParentVM = this, SlotButtons = "2 : None", ID = 2 });
SlotChildren.Add(new EEPROMSlotViewModel() { ParentVM = this, SlotButtons = "3 : None", ID = 3 });
SlotChildren.Add(new EEPROMSlotViewModel() { ParentVM = this, SlotButtons = "4 : None", ID = 4 });
SlotChildren.Add(new EEPROMSlotViewModel() { ParentVM = this, SlotButtons = "5 : None", ID = 5 });
SlotChildren.Add(new EEPROMSlotViewModel() { ParentVM = this, SlotButtons = "6 : None", ID = 6 });
}
generates 7 radiobuttons with ID related to each.
EEPROMSlotViewModel Class:
private string _SlotButtons;
public string SlotButtons
{
get; set;
}
private EEPROMViewModel _parentVm;
public EEPROMViewModel ParentVM
{
get; set;
}
private int _ID;
public int ID
{
get; set;
}
private bool _isChecked;
public bool IsChecked
{
get; set;
}
thus whenever I select a radiobutton and click SETSTRING button, the following code gets executed:
EEPROMSlotViewModel mSlotVM = new EEPROMSlotViewModel();
string label;
if (mSlotVM.ID == 0) //Accessing the 1st radiobutton clicked
{
label = string.Empty;
mSlotVM.getShortName(0, label);
if (label == string.Empty)
{
label = "None";
}
mSlotVM.SlotButtons = Convert.ToString(0 + ":" + label); // Setting CONTENT of radiobutton selected
}
Lets say I clicked 1st radio button, ID is supposed to be 0. It calls getShortName() method which does the following:
ParentVM.SelectedDaughterBoardBoxList = ParentVM.DaughterBoardBoxList[0];
ParentVM.SelectedDaughterVersionBoxList = ParentVM.DaughterVersionBoxList[0];
ParentVM.SelectedDaughterSerialBoxList = ParentVM.DaughterSerialBoxList[0];
shortlabel = "Hello";
I am facing few issues here:
Is mSlotVM right way to access other class members/function??
Once control enters getShortname(), it throws the excetion as follows: Object reference not set to an instance of an object. at
ParentVM.DaughterBoardBoxList[0];.
Even if I comment the first 3 statements in getShortName(), When getShortName gets called and once the control comes back, value of
label is "", i should be "hello".
I feel mSlotVm this is the reason behind the exception. Please help :)
No, you just create a new instance of the EEPROMSlotViewModel-Class, youre not accessing any of the RadioButtons ViewModels.
It would be helpful if you could show us your EEPROMViewModel-Class. I think the problem is, that your ParentVM.-Lists are null.
To achieve what you want, your getShortname()-method has to look like:
public void getShortname(int i, ref string shortlabel)
{
ParentVM.SelectedDaughterBoardBoxList = ParentVM.DaughterBoardBoxList[0];
ParentVM.SelectedDaughterVersionBoxList = ParentVM.DaughterVersionBoxList[0];
ParentVM.SelectedDaughterSerialBoxList = ParentVM.DaughterSerialBoxList[0];
shortlabel = "Hello";
}
EDIT:
Through EEPROMSlotViewModel mSlotVM = new EEPROMSlotViewModel(); you create a new instance of EEPROMSlotViewModel, but youre not getting the checked RadioButtons ViewModel. So at the point were you call mSlotVM.getShortName(0, label); mSlotVM has no ParentVM, thats what raises the exception. What you could do is go through your SlotChildren-List and take the EEPROMSlotViewModel whose IsChecked-property is true.
Example:
EEPROMSlotViewModel checkedVM;
string label = string.Empty;
foreach (EEPROMSlotViewModel vm in SlotChildren)
{
if (vm.IsChecked)
{
checkedVM = vm;
}
else
{
vm.SlotButtons = vm.ID + " : NONE"
}
}
checkedVM.getShortName(0, ref label);
if (label == string.Empty)
{
label = "None";
}
checkedVM.SlotButtons = Convert.ToString(0 + ":" + label); // Setting CONTENT of radiobutton selected
Related
please give me a hand! i have one simple WPF project, which it doesn't show the image. i have been struggling with it since one week, can not find my mistake! i looked a lot the solutions on this website, but still did not help me!
C# Code from Display Window
public partial class Boatdetails : Window
{
//public Boatdetails()
public Boatdetails(Object boot)
{
InitializeComponent();
if (boot is Ruderboot)
{
modell.Content = ((Ruderboot)boot).Modell;
plaetze.Content = ((Ruderboot)boot).Plaetze;
preis.Content = ((Ruderboot)boot).Preis;
bild.Content = ((Ruderboot)boot).Image;
HoheStack.Visibility = Visibility.Hidden;
MoroStack.Visibility = Visibility.Hidden;
}
else if (boot is Segelboote)
{
modell.Content = ((Segelboote)boot).Modell;
plaetze.Content = ((Segelboote)boot).Plaetze;
preis.Content = ((Segelboote)boot).Preis;
bild.Content = ((Segelboote)boot).Image;
hohe.Content = ((Segelboote)boot).Height;
HoheStack.Visibility = Visibility.Visible;
MoroStack.Visibility = Visibility.Hidden;
}
else
{
modell.Content = ((Motorboot)boot).Modell;
plaetze.Content = ((Motorboot)boot).Plaetze;
preis.Content = ((Motorboot)boot).Preis;
bild.Content = ((Motorboot)boot).Image;
motorModel.Content = ((Motorboot)boot).MotorModel;
motoLeistung.Content = ((Motorboot)boot).EnginePerformence;
HoheStack.Visibility = Visibility.Hidden;
MoroStack.Visibility = Visibility.Visible;
}
BitmapImage jpg = new BitmapImage(new Uri(((Boote)boot).Image, UriKind.Relative)); //Bild setzten, relativ im ordner images
Image img = new Image();
img.Source = jpg;
bild.Content = img;
}
private void showDetails(object detail)
{
spDetail.Height = 27;
lblDetails.Visibility = System.Windows.Visibility.Visible;
details.Visibility = System.Windows.Visibility.Visible;
}
}
and XML Window Code
<StackPanel>
<StackPanel Orientation="Horizontal">
<Label Content="Bild:" Width="100"/>
<Label x:Name="bild" Width="200" Height="200"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Content="Modell:" Width="100"/>
<Label x:Name="modell" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Content="Plätze:" Width="100"/>
<Label x:Name="plaetze" />
</StackPanel>
<StackPanel x:Name="spDetail" Orientation="Horizontal" Height="0">
<Label x:Name="lblDetails" Content="Details:" Width="100" Visibility="Hidden"/>
<Label x:Name="details" Visibility="Hidden"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Content="Preis:" Width="100"/>
<Label x:Name="preis" />
</StackPanel>
<StackPanel Orientation="Horizontal"
Name="HoheStack"
Visibility="Visible">
<Label Content="Hohe:" Width="100"/>
<Label x:Name="hohe" />
</StackPanel>
<StackPanel x:Name="MoroStack"
Visibility="Visible">
<StackPanel Orientation="Horizontal"
Visibility="Visible">
<Label Content="Moto Modell:" Width="100"/>
<Label x:Name="motorModel" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Content="Leistung" Width="100"/>
<Label x:Name="motoLeistung" />
</StackPanel>
</StackPanel>
</StackPanel>
this is how i have added object into the class:
rl.Add(new Ruderboot() { Modell = "XLight", Plaetze = 1, Preis = 3400, Image = "./Images/ruderboot1.jpg" });
and my class
public class Boote
{
public string Modell { get; set; }
public sbyte Plaetze { get; set; }
public float Preis { get; set; }
public string Image { get; set; }
public override string ToString()
{
return Modell + ": "+ Preis+"€";
}
}
Set the Build Action of the image files in your project to Resource (Solution Explorer -> Context Menu -> Properties) and load them by Resource File Pack URIs like
Image = "pack://application:,,,/Images/ruderboot1.jpg"
Besides that, you should use data binding. Assign the passed boat object to the DataContext of the Window:
public Boatdetails(Object boot)
{
DataContext = boot;
InitializeComponent();
}
In XAML, just write expressions like
<TextBlock Text="{Binding Modell}"/>
<Image Source="{Binding Image}"/>
where in the latter case the conversion from string to ImageSource is performed automatically by the framework.
You could use a single ContentControl with different DataTemplates for different boat types, like
<Window x:Class="BoatdetailsTest.Boatdetails" ...>
<Window.Resources>
<DataTemplate DataType="{x:Type local:Ruderboot}">
<StackPanel>
<!-- elements for Ruderboot -->
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Segelboot}">
<StackPanel>
<!-- elements for Segelboot -->
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<ContentControl Content="{Binding}"/>
</Grid>
</Window>
EditingModel.cs:
private ObservableCollection<string> color;
public ObservableCollection<string> Color
{
get { return color; }
set
{
color = value;
NotifyPropertyChanged("Color");
}
}
private ObservableCollection<string> shapes;
public ObservableCollection<string> Shapes
{
get { return shapes; }
set
{
shapes = value;
NotifyPropertyChanged("Shapes");
}
}
private ObservableCollection<string> size;
public ObservableCollection<string> Size
{
get { return size; }
set
{
size = value;
NotifyPropertyChanged("Size");
}
}
EditingsViewModel.cs:
private string selectedcolor;
public string SelectedColor
{
get { return selectedcolor; }
set
{
if (value != selectedcolor)
{
selectedcolor = value; NotifyPropertyChanged("SelectedColor");
}
}
}
private string selectedshapes;
public string SelectedShapes
{
get { return selectedshapes; }
set
{
if (value != selectedshapes)
{
selectedshapes = value; NotifyPropertyChanged("SelectedShapes");
}
}
}
private string selectedsize;
public string SelectedSize
{
get { return selectedsize; }
set
{
if (value != selectedsize)
{
selectedsize = value; NotifyPropertyChanged("SelectedSize");
}
}
}
XML document: (name of the xml doc is EditingsValue.xml)
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE MYEDITINGS[]>
<MYEDITINGS>
<Group name="GeneralEditings">
<EditingsName name="COLOR" value="red"/>
<EditingsName name="SHAPES" value="circle"/>
<EditingsName name="SIZE" value="medium"/>
<EditingsName name="FILE PATH" value="C:\ProgramFiles"/>
</Group>
</MYEDITINGS>
EditingsView.xaml:
<ComboBox SelectedValue="{Binding SelectedColor,Mode=TwoWay}" Height="25" Width="150" HorizontalContentAlignment="Right" VerticalAlignment="Center" ItemsSource="{Binding Color}"/ >
<ComboBox SelectedValue="{Binding SelectedShapes,Mode=TwoWay}" Height="25" Width="150" HorizontalContentAlignment="Right" VerticalAlignment="Center" ItemsSource="{Binding Shapes}"/ >
<ComboBox SelectedValue="{Binding SelectedSize,Mode=TwoWay}" Height="25" Width="150" HorizontalContentAlignment="Right" VerticalAlignment="Center" ItemsSource="{Binding Size}" />
<TextBox Height="26" Grid.Column="3" IsReadOnly="True" TextAlignment="Right" VerticalContentAlignment="Center" HorizontalAlignment="Left" VerticalAlignment="Center" Width="150" Text="{Binding ElementName=Mygroups, Path=DataContext.FolderPath,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" />
<Button KeyboardNavigation.TabIndex="2" Grid.Column="4" Content="Browse" Height="29" VerticalAlignment="Bottom" MinWidth="45" Command="{Binding ElementName=Mygeoups,Path=DataContext.FolderCommand}" CommandParameter="{Binding}" />
In my above code,I'm setting default value for my combo box using SelectedIndex,and then allowing the users to select their own value. Then I'm writing the selected values of user in XML document as mentioned above. Upto this everything is working fine.
But now my requirement is, if I open my application again,I should not get the default values in the combo boxes and textboxes, instead I should read the xml document and display the values of that in my combo boxes and textboxes.
How to achieve this using MVVM (wpf).
Can any one help me out.
Thanks in advance.
I think, this one help to you
For the EditingsViewModel.cs Constructor Read the Xml File, Assign the Values to Model
public EditingsViewModel()
{
ComboBoxModel = new EditingModel();
//Xml Path
string xmlpath = #"D:\MyDocument.xml";
var doc = new XmlDocument();
doc.Load(xmlpath);
XmlNode colorNode = doc.SelectSingleNode(#"/MYEDITINGS/Group/EditingsName[#name = 'COLOR']/#value");
XmlNode shapesNode = doc.SelectSingleNode(#"/MYEDITINGS/Group/EditingsName[#name = 'SHAPES']/#value");
XmlNode sizeNode = doc.SelectSingleNode(#"/MYEDITINGS/Group/EditingsName[#name = 'SIZE']/#value");
XmlNode filePathNode = doc.SelectSingleNode(#"/MYEDITINGS/Group/EditingsName[#name = 'FILE PATH']/#value");
//Binding the Color to the Color Property
var observableColors = new System.Collections.ObjectModel.ObservableCollection<string>() { "red","yellow","green"};
ComboBoxModel.Color = observableColors;
//Binding the Shapes to the Shape Property
var observableShapes = new System.Collections.ObjectModel.ObservableCollection<string>() { "circle", "Triangle", "Rectangle" };
ComboBoxModel.Shapes = observableShapes;
//Binding the Size to the Size Property
var observableSize = new System.Collections.ObjectModel.ObservableCollection<string>() { "medium", "high", "low" };
ComboBoxModel.Size = observableSize;
//Assign the Color Default vlaue from the Xml Document
SelectedColor = colorNode.Value;
//Assign the Shape Default vlaue from the Xml Document
SelectedShapes = shapesNode.Value;
//Assign the Size Default vlaue from the Xml Document
SelectedSize = sizeNode.Value;
//Assign the FilePath Default vlaue from the Xml Document
FolderPath = filePathNode.Value;
}
EditingsView.xaml - Remove the Selected Index Property
<ComboBox SelectedValue="{Binding SelectedColor,Mode=TwoWay}" Height="25" Width="150" HorizontalContentAlignment="Right" VerticalAlignment="Center" ItemsSource="{Binding ComboBoxModel.Color}"/>
<ComboBox SelectedValue="{Binding SelectedShapes,Mode=TwoWay}" Height="25" Width="150" HorizontalContentAlignment="Right" VerticalAlignment="Center" ItemsSource="{Binding ComboBoxModel.Shapes}"/>
<ComboBox SelectedValue="{Binding SelectedSize,Mode=TwoWay}" Height="25" Width="150" HorizontalContentAlignment="Right" VerticalAlignment="Center" ItemsSource="{Binding ComboBoxModel.Size}" />
<TextBox Name="Mygroups" Height="26" Grid.Column="3" IsReadOnly="True" TextAlignment="Right" VerticalContentAlignment="Center" HorizontalAlignment="Left" VerticalAlignment="Center" Width="150" Text="{Binding ElementName=Mygroups, Path=DataContext.FolderPath,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" />
<Button KeyboardNavigation.TabIndex="2" Grid.Column="4" Content="Browse" Height="29" VerticalAlignment="Bottom" MinWidth="45" Command="{Binding ElementName=Mygeoups,Path=DataContext.FolderCommand}" CommandParameter="{Binding}" />
When App opens, selectedItem of the ListPicker namely, "BackgroundColor" must be from variable. How to achieve this?
XAML:
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Name="PickerItemTemplate">
<TextBlock Text="{Binding BackGroundColorString}" />
</DataTemplate>
<DataTemplate x:Name="PickerFullModeItemTemplate" >
<Grid x:Name="rootGrid" Margin="0">
<StackPanel Orientation="Horizontal" Margin="0 14 0 0" HorizontalAlignment="Center">
<TextBlock Name="BackgroundColor"
Text="{Binding BackGroundColorString}"
FontSize="35"
Margin="10,10"
TextAlignment="Center"
FontFamily="/Assets/Fonts/AGENCYR.TTF#Agency FB"
/>
</StackPanel>
</Grid>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
<toolkit:ListPicker x:Name="BackgroundColor" FullModeHeader="Select Background Color:"
Header="Background Color:" BorderThickness="0"
FullModeItemTemplate="{StaticResource PickerFullModeItemTemplate}"
ItemTemplate="{StaticResource PickerItemTemplate}" Background="#FF09043C"
SelectionChanged="BackgroundColor_SelectionChanged" >
</toolkit:ListPicker>
C#:
public class BackGroundlistPickerClass
{
public string BackGroundColorString
{
get;
set;
}
}
List<BackGroundlistPickerClass> BackGroundColorList = new List<BackGroundlistPickerClass>();
public void ImplementListPickeritems() //Listpickers
{
BackGroundColorList.Add(new BackGroundlistPickerClass() { BackGroundColorString = "White (Default)" });
BackGroundColorList.Add(new BackGroundlistPickerClass() { BackGroundColorString = "Black" });
BackGroundColorList.Add(new BackGroundlistPickerClass() { BackGroundColorString = "Light Grey" });
}
string PreSelectedColor="Black";
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
BackgroundColor.SelectedItem=PreSelectedColor; // ERROR COMES ON THIS LINE
}
BackgroundColor.SelectedItem is not working because, items in BackgroundColor are acutaly from Class/List. Now how to set BackgroundColor listpicker to Black(PreSelectedColor) whenever the page opens?
You need to set SelectedItem to an item from the ItemsSource. You can try this way, assuming that BackGroundColorList property used for ItemsSource :
string PreSelectedColor="Black";
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
var defaultColor =
BackGroundColorList.FirstOrDefault(o => o.BackGroundColorString == PreSelectedColor);
BackgroundColor.SelectedItem = defaultColor;
}
When I adding Genre of book by Listpicker, it's successful but when I choose the Book title in Listbox in order to show the details of Book, the value of Genre does not pass. What I want is in detail page, Genre is showed in Listpicker (as in Add page) and show the Genre I had chosen before
Addpage.xaml
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Name="listpickertemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Genre}" Margin="10 0 0 0" />
</StackPanel>
</DataTemplate>
<Grid x:Name="ContentPanel1" Grid.Row="1" >
<ListBox x:Name="BookInfo" >
<TextBlock Text="Book Title: *" FontWeight="Normal" FontStyle="Normal" Style="{StaticResource PhoneTextTitle3Style}" />
<TextBox x:Name="booktitletext" Width="460" TextWrapping="Wrap"/>
<TextBlock Text="Genre: *" FontWeight="Normal" FontStyle="Normal" Style="{StaticResource PhoneTextTitle3Style}" />
<toolkit:ListPicker x:Name="ListPicker" ItemTemplate="{StaticResource listpickertemplate}" Width="120" HorizontalAlignment="Left"/>
</ListBox>
</Grid>
The code behind Addpage:
public AddingPage()
{
InitializeComponent();
this.DataContext = App.MainViewModel;
List<GenrePicker> newpicker = new List<GenrePicker>();
newpicker.Add(new GenrePicker() { Genre = "Comedy",Index = 0 });
newpicker.Add(new GenrePicker() { Genre = "Science",Index = 1 });
newpicker.Add(new GenrePicker() { Genre = "Action", Index = 2 });
this.ListPicker.ItemsSource = newpicker;
}
private void Add_Click(object sender, EventArgs e)
{
if (booktitletext.Text.Length > 0)
{
Book newbook = new Book
{
BookTitle = booktitletext.Text,
Genre = (ListPicker.SelectedItem as GenrePicker).Genre.ToString(),
}
App.MainViewModel.Addinfo(newbook);
}
}
In my Browsepage.xaml, I just show the title of the book
<Grid x:Name="ContentPanel1" Margin="12,0,12,0">
<ListBox x:Name="TitleList" SelectionChanged="TitleList_SelectionChanged" ItemsSource="{Binding Load0}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Width="466" Margin="0, 0, 0, 12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="360"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0"></Grid>
<StackPanel Grid.Column="1">
<TextBlock FontSize="40" Text="{Binding BookTitle}" FontWeight="Normal" FontStyle="Normal" Style="{StaticResource PhoneTextTitle3Style}" TextWrapping="Wrap"/>
</StackPanel>
<Grid Grid.Column="2">
<Button x:Name="Deletebutton" Height="50" Width="50" Click="deleteButton_Click" BorderBrush="{StaticResource TransparentBrush}" Margin="-40">
<Image Source="/Assets/delete.dark.png" Height="50" Width="50" Visibility="{StaticResource PhoneDarkThemeVisibility}" Margin="-40" />
</Button>
</Grid>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
The code behind of Browsepage when i choose a book title:
private void TitleList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// If no Book is selected, just return
if (TitleList.SelectedIndex== -1) return;
// Get the parent application that contains the Book being edited
App thisApp = Application.Current as App;
// Set this to the selected customer
thisApp.SelectedBook = TitleList.SelectedItem as Book;
thisApp.SelectedGenre = TitleList.SelectedItem as GenrePicker;
// Navigate to the detail page
NavigationService.Navigate(new Uri("/View/DetailPage/BookDetail.xaml",UriKind.RelativeOrAbsolute));
TitleList.SelectedIndex = -1;
}
And the Bookdetails.xaml:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0" >
<ListBox x:Name="BookDetails">
<TextBlock x:Name="booktitle" Text="Book Title:" Foreground="#FF3B12AA" FontSize="30" FontWeight="Bold" FontFamily="Courier New"/>
<TextBox x:Name="booktitletext" Text="{Binding BookTitle, Mode=TwoWay}" Width="460" TextWrapping="Wrap" Background="#BF22A1DC" BorderBrush="#BFFFFFFF" FontFamily="Tahoma" FontSize="26"/>
<TextBlock x:Name="author" Text="Author:" Foreground="#FF3B12AA" FontSize="30" FontWeight="Bold" FontFamily="Courier New"/>
<TextBox x:Name="authortext" Tap="authortext_Tap" Text="{Binding Author, Mode=TwoWay}" Width="460" TextWrapping="Wrap" Background="#BF22A1DC" BorderBrush="#BFFFFFFF" FontFamily="Tahoma" FontSize="26"/>
<TextBlock x:Name="genre" Text="Genre:" Foreground="#FF3B12AA" FontSize="30" FontWeight="Bold" FontFamily="Courier New"/>
<toolkit:ListPicker x:Name="ListPicker" ItemTemplate="{StaticResource listpickertemplate}" Width="120" HorizontalAlignment="Left" Background="#BF3BDC22" SelectedIndex="{Binding Index}"/>
</ListBox>
</Grid>
the code-behind Bookdetails page:
public BookDetail()
{
InitializeComponent();
this.DataContext = App.MainViewModel;
List<GenrePicker> newpicker = new List<GenrePicker>();
newpicker.Add(new GenrePicker() { Genre = "Comedy",Index = 0});
newpicker.Add(new GenrePicker() { Genre = "Science", Index = 1 });
newpicker.Add(new GenrePicker() { Genre = "Action", Index = 2});
this.ListPicker.ItemsSource = newpicker;
}
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
// Get the parent application
App thisApp = Application.Current as App;
// Load the active customer into the viewmodel
App.MainViewModel.LoadDetails(thisApp.SelectedBook,thisApp.SelectedGenre);
}
and this is the Loadtails function
public void LoadDetails(Book bcd,GenrePicker xyz)
{
Index = xyz.Index;
BookTitle = bcd.BookTitle;
Genre = bcd.Genre;
}
I have try emulate it but it show error when I choose the booktile System.InvalidOperationException: SelectedIndex must always be set to a valid value.
at this.DataContext = App.MainViewModelof Bookdetails Page
My guess, the problem is your code setting DataContext (which means setting ListPicker's selected index too) before populating ListPicker's ItemsSource. That will cause selecting a non-existent -yet- Item of the ListPicker. Try to reorder codes to populate ListPicker before setting DataContext :
public BookDetail()
{
InitializeComponent();
List<GenrePicker> newpicker = new List<GenrePicker>();
newpicker.Add(new GenrePicker() { Genre = "Comedy",Index = 0});
newpicker.Add(new GenrePicker() { Genre = "Science", Index = 1 });
newpicker.Add(new GenrePicker() { Genre = "Action", Index = 2});
this.ListPicker.ItemsSource = newpicker;
this.DataContext = App.MainViewModel;
}
Instead of SelectedIndex = -1, try SelectedItem = null, which makes more sense.
When you set SelectedIndex = -1, you tell the ListPicker, "Hey, go find the -1'th element in your list and set that as selected." Then your ListPicker crashes because it doesn't understand what ListPicker[-1] means.
I'm writing a Silverlight 5 web application using the DataGrid control. I have an interesting issue indeed.
I'm using templated columns for each row. Each row represents one data item in an observable collection.
Each row holds one check box, one text block, and one text box.
The environment that my error occurs in is one where there are more rows than silverlight can draw on screen thus enables the vertical scollbar.
when a user inputs information into more than one text box and/or more than one checkbox then scrolls down random boxes are checked and random text boxes are populated with similar/partial input from previously populated text boxes.
when a user scrolls up and then back down different rows are populated at random. I've tried this with bound and unbound inputs and the result is the same.
I've mocked up an example that shows this issue
here is the xaml for the MainPage.xaml
<UserControl x:Class="DataGrid_bug_repro.MainPage"
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:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"
mc:Ignorable="d"
d:DesignHeight="600" d:DesignWidth="800">
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel>
<TextBlock Margin="60 0 0 0">Bound to Data Items</TextBlock>
<sdk:DataGrid Name="dgBound" Height="280" Width="680" AutoGenerateColumns="False" FontSize="12" >
<sdk:DataGrid.Columns>
<sdk:DataGridTemplateColumn Header="Select" >
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel>
<CheckBox Width="40" Tag="{Binding ID}" IsChecked="{Binding Selected}" />
</StackPanel>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
<sdk:DataGridTemplateColumn Header="name" >
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel>
<Grid>
<TextBlock TextWrapping="Wrap" Text="{Binding Name}" TextOptions.TextFormattingMode="Ideal" />
</Grid>
</StackPanel>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
<sdk:DataGridTemplateColumn Header="txt" >
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel>
<Grid>
<TextBox Text="{Binding txt}" />
</Grid>
</StackPanel>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
<TextBlock Margin="60 0 0 0">Not Bound to Data Items</TextBlock>
<sdk:DataGrid Name="dgNotBound" Height="280" Width="680" AutoGenerateColumns="False" FontSize="12" >
<sdk:DataGrid.Columns>
<sdk:DataGridTemplateColumn Header="Select" >
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel>
<CheckBox Width="40" Tag="{Binding ID}" />
</StackPanel>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
<sdk:DataGridTemplateColumn Header="name" >
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel>
<Grid>
<TextBlock TextWrapping="Wrap" Text="{Binding Name}" TextOptions.TextFormattingMode="Ideal" />
</Grid>
</StackPanel>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
<sdk:DataGridTemplateColumn Header="txt" >
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel>
<Grid>
<TextBox Text="" />
</Grid>
</StackPanel>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
</StackPanel>
</Grid>
</UserControl>
Here is the C# code for the MainPage.xaml.cs file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Collections.ObjectModel;
namespace DataGrid_bug_repro
{
public class ITEM : INotifyPropertyChanged
{
private string _ID = string.Empty;
private bool _Selected = false;
private string _Name = string.Empty;
private string _txt = string.Empty;
public string ID
{
get{return _ID;}
set { _ID = value; onPropertyChanged(this, "ID"); }
}
public string Name
{
get { return _Name; }
set { _Name = value; onPropertyChanged(this, "Name"); }
}
public string txt
{
get { return _txt; }
set { _txt = value; onPropertyChanged(this, "txt"); }
}
public bool Selected
{
get { return _Selected; }
set { _Selected = value; onPropertyChanged(this, "Selected"); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void onPropertyChanged(object sender, string propertyName)
{
if (this.PropertyChanged != null)
{
PropertyChanged(sender, new PropertyChangedEventArgs(propertyName));
}
}
}
public partial class MainPage : UserControl
{
public MainPage()
{
ObservableCollection<ITEM> Items = new ObservableCollection<ITEM> {
new ITEM { ID="1", Name="Gomez" },
new ITEM { ID="2", Name="Morticia" },
new ITEM { ID="3", Name="Pugsly" },
new ITEM { ID="4", Name="Wednesday" },
new ITEM { ID="5", Name="Pubert" },
new ITEM { ID="6", Name="Uncle Fester" },
new ITEM { ID="7", Name="Grandmama" },
new ITEM { ID="8", Name="Thing" },
new ITEM { ID="9", Name="Lurch" },
new ITEM { ID="10", Name="Cousin Itt" },
new ITEM { ID="11", Name="Cousin Cackle" },
new ITEM { ID="12", Name="Kitty Cat" },
new ITEM { ID="13", Name="Aristotle" },
new ITEM { ID="14", Name="Homer" },
new ITEM { ID="15", Name="Tristan" },
new ITEM { ID="16", Name="Isolde" },
new ITEM { ID="17", Name="Zelda" },
new ITEM { ID="18", Name="Cleopatra" },
new ITEM { ID="19", Name="Bernice" },
new ITEM { ID="20", Name="Ophelia" },
new ITEM { ID="21", Name="Melancholia" },
new ITEM { ID="22", Name="Hester" },
new ITEM { ID="23", Name="Norman Normanmeyers" },
new ITEM { ID="24", Name="Normina Normanmeyers" },
new ITEM { ID="25", Name="N.J. Normanmeyers" } };
InitializeComponent();
dgBound.ItemsSource = Items;
dgNotBound.ItemsSource = Items;
}
}
}
Has anyone seen this before? and is there a work around? Am I missing something obvious?
Thanks in advance :)
I've had this problem too in the past, and I don't remember exactly how to fix it. But, looking at the code this might be it:
Try adding an event handler in your code behind for IsKeyboardFocusWithinChanged like so,
private void DataGrid_IsKeyboardFocusWithinChanged(object sender, System.Windows.DependencyPropertyChangedEventArgs e)
{
(sender as DataGrid).CommitEdit(DataGridEditingUnit.Row, true);
}
If this doesn't work, I'll delete my answer.
It turns out that Utilizing TwoWay binding mode actually nullifies this issue. I'm not sure why but it probably has something to do with row visualization. I just thought I'd let you all know the work around.