Binding data in stackpanel - c#

I use WPF and c#.
I have an issue regarding binding and visibility.
I have a tree which is bound to obsCol1. Then I have a form in a grid whose datacontext is set to `
DataContext="{Binding ElementName=tree, Path=SelectedItem}">`
Inside that form I have 3 identical subforms if you will. Each of the 3 subforms is a groupbox inside of which is a horizontal stack panel in which there is a label textbox label textbox button.
<GroupBox Grid.Column="3" Grid.Row="8" Grid.ColumnSpan="3">
<GroupBox.Header>Reklama 1</GroupBox.Header>
<StackPanel Name="Rek1" DataContext="Reklame" Orientation="Horizontal">
<Label Grid.Column="3" Grid.Row="10" HorizontalAlignment="Right" VerticalAlignment="Top">Datum post/zam</Label>
<xctk:DateTimePicker x:Name="dtReklama1"
Grid.Row="10"
Grid.Column="4"
Height="25"
Margin="3"
Padding="3"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Width="150" Value="{Binding Path=Opr_brendiranje}"/>
<Label Grid.Column="3" Grid.Row="8" HorizontalAlignment="Right" VerticalAlignment="Top">Dimenzija</Label>
<extToolkit:WatermarkTextBox x:Name="Reklama" Grid.Row="8"
Grid.Column="4"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Width="100"
Height="25"
Padding="3"
Margin="3"
AcceptsReturn="True"
Validation.ErrorTemplate="{StaticResource ValidationTemplate}"
Validation.Error="Validation_Error">
<extToolkit:WatermarkTextBox.Watermark>
<TextBox Text="Reklama" Margin="4,2,2,0" FontWeight="Regular" Foreground="Silver" BorderThickness="0"/>
</extToolkit:WatermarkTextBox.Watermark>
<extToolkit:WatermarkTextBox.Text>
<Binding Path="RekDimenzije" UpdateSourceTrigger="PropertyChanged" NotifyOnValidationError="True"/>
</extToolkit:WatermarkTextBox.Text>
</extToolkit:WatermarkTextBox>
<Button Grid.Column="5" Grid.Row="9" Height="20" Width="15" Click="Dodaj_Reklamu" VerticalAlignment="Top" FontWeight="Bold" Margin="5" >+</Button>
</StackPanel>
</GroupBox>
So now I need to bind this but the issue is that these subforms use a different class from the form itself. They are an entity in and of itself. So I was wondering if there was any way to bind them independently somehow like itemsource the groupbox or the stack panel or soemthing. I tried using itemscontrol and binding to it but that did not work it would bind the itemsource but if the itemsource was empty the control would dissapear therefore not allowing the user to add it.
Any help would be appreciated.
Update:
Ok so I have a single usercontrol.
On the left side is a tree that uses a HierarchicalDataTemplate that is bound to 2 different classes one of which OrgSredstva is OrgClass with Sredstva class contained within.
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Org_Sredstva}">
<HierarchicalDataTemplate.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="Focusable" Value="False"/>
</Style>
</HierarchicalDataTemplate.ItemContainerStyle>
<TextBlock Text="{Binding Path=Organizacije_Naziv}"/>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Ossr_Naziv}"/>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
This all works as complicated as it sounds the tree works fine.
On the right side is a grid that like i described above has datacontext set to whatever is selected in the tree. I need this so that when the selection changes in the tree the form changes with it. The issue is that neither of the classes the tree is bound to is the class the form should be bound to. So the grid can't find the data because the textbox bindings aren't in that observable collection but another one. The way I solved this is to bind every textbox.text property in codebehind so
public void OdabranoDrvo()
{
OdabranaOrg = this.View.tree.SelectedItem as Organizacije;
if (OdabranaOrg != null)
{
string orgId = OdabranaOrg.Organizacije_Sifra;
IEnumerable<Opremljenost> odabranaOpr = from fn in _oprema
where fn.Opr_org_sifra == orgId
select fn;
var ob = new ObservableCollection<Opremljenost>(odabranaOpr);
if (ob.Count > 0)
{
foreach (Opremljenost opr in odabranaOpr)
{
this.View.Povrsina.Text = opr.Opr_Povrsina.ToString();
this.View.RadnoVrijeme.Text = opr.Opr_RadnoVrijeme;
if (opr.Opr_Vlasnik == 1)
{
this.View.LutRad.IsChecked = true;
this.View.ImeVlasnika.IsReadOnly = true;
}
else
{
this.View.LutRad.IsChecked = false;
this.View.ImeVlasnika.IsReadOnly = false;
}
this.View.ImeVlasnika.Text = opr.Opr_ime_vlasnik;
if (opr.Opr_brojilo == 1)
{
this.View.Brojilo.IsChecked = true;
}
else
{
this.View.Brojilo.IsChecked = false;
}
if (opr.Opr_ventilacija == 1)
{
this.View.Ventilacija.IsChecked = true;
}
else
{
this.View.Ventilacija.IsChecked = false;
}
this.View.dtBrendiranje.Value = opr.Opr_brendiranje;
this.View.dtKrecenje.Value = opr.Opr_krecenje;
this.View.Napomena.Text = opr.Opr_napomena;
this.View.BrojAparata.Text = opr.Opr_broj_aparata.ToString();
this.View.BrojRuleta.Text = opr.Opr_broj_ruleta.ToString();
this.View.UkupanBrojKlima.Text = opr.Opr_uku_br_klima.ToString();
this.View.BrojKlimaLutrija.Text = opr.Opr_br_kl_lut.ToString();
this.View.UkupanBrojTv.Text = opr.Opr_uku_broj_tv.ToString();
this.View.BrojTvLutrija.Text = opr.Opr_broj_tv_lut.ToString();
this.View.BrojTvPartneri.Text = opr.Opr_broj_tv_partneri.ToString();
this.View.StrujnaSnaga.Text = opr.Opr_struja_ang_snaga.ToString();
_slikeOpr = Ap.GlavniRepository.UcitajSlikeZaOpremu(opr.Opr_Id);
this.View.Thumbnails.ItemsSource = _slikeOpr;
_reklame = Ap.GlavniRepository.UcitajReklameZaOpremu(opr.Opr_Id);
int i = _reklame.Count();
if (i == 2)
{
this.View.Rek2.Visibility = Visibility.Visible;
this.View.Rek3.Visibility = Visibility.Collapsed;
}
else if (i == 3)
{
this.View.Rek2.Visibility = Visibility.Visible;
this.View.Rek3.Visibility = Visibility.Visible;
}
else
{
this.View.Rek2.Visibility = Visibility.Collapsed;
this.View.Rek3.Visibility = Visibility.Collapsed;
}
this.View.Reklame.DataContext = _reklame;
}
}
else
{
this.View.Povrsina.Text = "0";
this.View.RadnoVrijeme.Text = String.Empty;
this.View.LutRad.IsChecked=false;
this.View.ImeVlasnika.Text = String.Empty;
this.View.Brojilo.IsChecked = false;
this.View.Ventilacija.IsChecked = false;
this.View.dtBrendiranje.Value = DateTime.Now;
this.View.dtKrecenje.Value = DateTime.Now;
this.View.Napomena.Text = String.Empty;
this.View.BrojAparata.Text = "0";
this.View.BrojRuleta.Text = "0";
this.View.UkupanBrojKlima.Text = "0";
this.View.BrojKlimaLutrija.Text = "0";
this.View.UkupanBrojTv.Text = "0";
this.View.BrojTvLutrija.Text = "0";
this.View.BrojTvPartneri.Text = "0";
this.View.StrujnaSnaga.Text = "0";
this.View.Thumbnails.ItemsSource = null;
this.View.Rek2.Visibility = Visibility.Collapsed;
this.View.Rek3.Visibility=Visibility.Collapsed;
}
}
}
The original question i resolved by creating a new grid inside my preexisting grid and just setting the data context for that inner grid to what I needed it to be. Now I find that all the bindings seem to work at least on reading from database, haven't tested inserting into database yet.
I realise this is all very ugly but I couldn't figure out a way to actually bind it while it still working as it should...

Related

TextBlock with text highlighting

Faced the need to select a fragment of text in TextBlock, namely certain keywords on which the ListBox was filtered, this text block itself and containing
XAML variant, title property is not bound
<ListBox Name="ProcedureList" ItemsSource="{Binding Path=ProceduresView.View}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Name="ProcedurePanel" PreviewMouseDown="ProcedurePanel_OnPreviewMouseDown">
<DockPanel Width="{c:Binding ElementName=MainPanel, Path=Width-40}">
<!--<TextBlock Name="MainText" TextWrapping="Wrap" FontSize="16" Text="{Binding Path=title}" HorizontalAlignment="Left" />-->
<htb:HighlightTextBlock Name="MainText" TextWrapping="Wrap" FontSize="16" Text="{Binding Path=title}" HorizontalAlignment="Left">
<htb:HighlightTextBlock.HighlightRules>
<htb:HighlightRule
IgnoreCase="{Binding IgnoreCase, Source={StaticResource SourceVm}}"
HightlightedText="{Binding Path=title, Converter={StaticResource getFilter}}">
<htb:HighlightRule.Highlights>
<htb:HighlightBackgroung Brush="Yellow"/>
</htb:HighlightRule.Highlights>
</htb:HighlightRule>
</htb:HighlightTextBlock.HighlightRules>
</htb:HighlightTextBlock>
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
A component written by our compatriot with open source is used
Component
Description of component
The commented code is an old TexBlock with no selection
The new HighlightTextBlock component perfectly selects the text if you use a static resource, as in the example, but when I try to bind it to the current text it can not find this field :(, I'm new in WPF help figure it out
HightlightedText="{Binding Path=title, Converter={StaticResource getFilter}}"
How correctly to anchor this property to title?
DataContext structure
public ObservableCollection<Procedure> Procedures { set; get; }
public CollectionViewSource ProceduresView { set; get; } = new CollectionViewSource();
....
Procedures = new ObservableCollection<Procedure>();
ProceduresView.Filter += Procedures_Filter;
ProceduresView.Source = Procedures;
....
public class Procedure : ObservableObject
{
....
public String title { get; set; }
....
}
....
// Simple filtering
void Procedures_Filter(object sender, FilterEventArgs e)
{
Procedure procedure = (Procedure) e.Item;
Boolean flag = false;
if (!string.IsNullOrEmpty(filter))
{
Setting.Filter sfilter = new Setting.Filter();
sfilter.type = "искать везде";
sfilter.text = filter;
ObservableCollection<Setting.Filter> arr = new ObservableCollection<Setting.Filter>();
arr.Add(sfilter);
if (Utils.AssignedProcedureFromFilter(procedure, arr)) flag = true;
}
else flag = true;
e.Accepted = flag;
}
Video with problem description
Simplified project emitting my functional
On the Russian-speaking forum they explained to me that:
Your case, in fact, is more serious. DataContext you, apparently, the
right one. But your Binding expression is inside the HighlightRules
property setter, which is not part of the visual tree (because it is
not available as a Child element of your control). And elements that
are not inside the visual tree, participate in bindings are only
limited: they do not inherit DataContext, nor access by name through
ElementName. As a solution, bind to an element via x: Reference. In my
(heavily cut) test case, HightlightedText = "{Binding Path =
DataContext.title, Source = {x: Reference MainText}} is triggered."
But, if directly replaced by this, a strange error works: 'Can not
call MarkupExtension. ProvideValue because of a cyclic dependency. The
properties inside the MarkupExtension can not reference objects that
reference the MarkupExtension result.
The workaround for the error was found here: you need to put your element in resources. We get this:
XAML, modified according to the recommendations
<ListBox Name="ProcedureList" ItemsSource="{Binding Path=ProceduresView.View}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Name="ProcedurePanel" PreviewMouseDown="ProcedurePanel_OnPreviewMouseDown">
<DockPanel Width="{c:Binding ElementName=MainPanel, Path=Width-40}">
<!--<TextBlock Name="MainText" TextWrapping="Wrap" FontSize="16" Text="{Binding Path=title}" HorizontalAlignment="Left" />-->
<htb:HighlightTextBlock Name="MainText" TextWrapping="Wrap" FontSize="16"
Text="{Binding Path=title}" HorizontalAlignment="Left">
<htb:HighlightTextBlock.Resources>
<htb:HighlightRule x:Key="HR"
IgnoreCase="{Binding IgnoreCase, Source={StaticResource SourceVm}}"
HightlightedText="{Binding Path=DataContext.title, Source={x:Reference MainText}, Converter={StaticResource getFilter}}">
<htb:HighlightRule.Highlights>
<htb:HighlightBackgroung Brush="Yellow"/>
</htb:HighlightRule.Highlights>
</htb:HighlightRule>
</htb:HighlightTextBlock.Resources>
<htb:HighlightTextBlock.HighlightRules>
<htb:HighlightRulesCollection>
<StaticResource ResourceKey="HR"/>
</htb:HighlightRulesCollection>
</htb:HighlightTextBlock.HighlightRules>
</htb:HighlightTextBlock>
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I was given advice on the restructuring of XAML, through resources, this partially solved the problem (I successfully got the title text in the converter), but the element ceased to perform its functions (allocation) During the discussion, it was suggested that the component itself should be finalized
#iRumba: In theory, the whole trick should not be necessary if you put
the HighlighRule collection (also) in a visual tree. Then the
DataContext will be automatically inherited and on idea the binding
through ElementName too will work.
#iRumba: I do not remember exactly. It seems, it is necessary to
specify to add all HighlightRule as LogicalChildren (for this purpose
on idea it is necessary to redefine protected internal override
IEnumerator LogicalChildren). This is a complicated, advanced
technique, yes.
Sorry for Google Translator
Found a solution
public class SearchHightlightTextBlock : TextBlock
{
public SearchHightlightTextBlock() : base() { }
public String SearchText
{
get { return (String)GetValue(SearchTextProperty); }
set { SetValue(SearchTextProperty, value); }
}
private static void OnDataChanged(DependencyObject source,
DependencyPropertyChangedEventArgs e)
{
TextBlock tb = (TextBlock)source;
if (tb.Text.Length == 0)
return;
string textUpper = tb.Text.ToUpper();
String toFind = ((String)e.NewValue).ToUpper();
int firstIndex = textUpper.IndexOf(toFind);
String firstStr = "";
String foundStr = "";
if (firstIndex != -1)
{
firstStr = tb.Text.Substring(0, firstIndex);
foundStr = tb.Text.Substring(firstIndex, toFind.Length);
}
String endStr = tb.Text.Substring(firstIndex + toFind.Length,
tb.Text.Length - (firstIndex + toFind.Length));
tb.Inlines.Clear();
tb.FontSize = 16;
var run = new Run();
run.Text = firstStr;
tb.Inlines.Add(run);
run = new Run();
run.Background = Brushes.Yellow;
run.Text = foundStr;
tb.Inlines.Add(run);
run = new Run();
run.Text = endStr;
tb.Inlines.Add(run);
}
public static readonly DependencyProperty SearchTextProperty =
DependencyProperty.Register("SearchText",
typeof(String),
typeof(SearchHightlightTextBlock),
new FrameworkPropertyMetadata(null, OnDataChanged));
}
Use
<parser:SearchHightlightTextBlock SearchText="{Binding Path=title, Converter={StaticResource getFilter}}" Text="{Binding title}"/>

Reach a TextBlock from a specific ListViewItem from the ListView in Windows Phone 8.1 XAML programmatically

I am a new developer on Windows Phone 8.1, I am try to reach a specific ListView item from the ListView collection and be able to color it or color the TextBock inside of it, But I can't reach the item or reach any of items inside of ListView, Please take a look for my below code :
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
SQLiteRT db1 = new SQLiteRT();
var db_connection = await db1.Connection("MyDB.sqlite");
List<MyTBL> t_list = db1.GetTable("SELECT * FROM MyTBL LIMIT 4 ORDER BY RANDOM() ;");
db_connection.Close();
LV_Options.ItemsSource = t_list;
}
// my List View called LV_Options
private void LV_Options_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListView lv1 = sender as ListView;
if (lv1 == null)
return;
MyTBL wrd = lv1.SelectedItem as MyTBL;
if (wrd == null)
return;
TextBlock tb = lv1.FindName("TB_AMean1") as TextBlock;
tb.FontSize = 17; // here I got debug error (it not worked !!!!!!!)
var item = LV_Options.Items.ElementAt(3); // this seems not work also !!!!
item.BackColor = Color.LightSteelBlue;
}
As you can see above, I tried to reach a specific item by LV_Options.Items.ElementAt(3) but it doesn't work! I also tried to reach the TextBlock from the selected List view item, but also not worked !
(Updated)
XAML code :
<!-- Title Panel -->
<StackPanel Grid.Row="0" Margin="19,0,0,0">
<TextBlock Name="TB_Rslt" Text="Here result of your answer" Style="{ThemeResource TitleTextBlockStyle}" Margin="0,12,0,0"/>
<TextBlock Text="page title" Margin="0,-6.5,0,26.5" Style="{ThemeResource HeaderTextBlockStyle}" CharacterSpacing="{ThemeResource PivotHeaderItemCharacterSpacing}"/>
</StackPanel>
<!--TODO: Content should be placed within the following grid-->
<Grid Grid.Row="1" x:Name="ContentRoot" Margin="19,10,19,15">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Name="TB_Question" Text="Choose Answer " Margin="0,0,25,0" HorizontalAlignment="Right" FontWeight="Bold" FontSize="22" FontFamily="Verdana" RenderTransformOrigin="0.5,0.5" />
<TextBlock Name="TB_EnWord" Text="" Margin="90,0,15,0" HorizontalAlignment="Left" FontWeight="Bold" FontSize="22" FontFamily="Verdana" RenderTransformOrigin="0.5,0.5" TextAlignment="Right" />
<StackPanel Grid.Row="1" Margin="5,22,0,0">
<ListView Name="LV_Options" SelectionChanged="LV_Options_SelectionChanged">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Margin="6">
<StackPanel VerticalAlignment="Top" Margin="10,0,0,0">
<TextBlock Name="TB_AMean1" Text="{Binding AMean1}" TextWrapping="Wrap"/>
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
<Button Name="Btn_Answer" Content="Ansewr" HorizontalAlignment="Left" Grid.Row="1" VerticalAlignment="Bottom" Click="Btn_Answer_Click"/>
My application is a quiz application that offer 4 choices/options as answers for each question, and when user select a true answer, I want to highlight the true answer(true choice) by make its background to green, and if the user selected wrong answer/option I want to make the background of that answer (a specific List View item) with red.
Any help please ?
You're not going to be able to access an element inside a data template like that. Instead, leverage the binding to a view model to set the color and other view-related properties. First, create a wrapper view model for your data class:
public class MyTBLViewModel : INotifyPropertyChanged
{
public MyTBL Entity
{
get { return _entity; }
}
private readonly MyTBL _entity;
public Brush Highlight
{
get { return _brush; }
set
{
_brush = value;
RaisePropertyChanged("Highlight");
}
}
private Brush _highlight;
public double ItemFontSize
{
get { return _itemFontSize; }
set
{
_itemFontSize = value;
RaisePropertyChanged("ItemFontSize");
}
}
private Brush _itemFontSize;
public MyTBLViewModel(MyTBL entity)
{
_entity = entity;
_highlight = new SolidColorBrush(Colors.Transparent);
_itemFontSize = 12;
}
public event PropertyChangedEventArgs PropertyChanged;
protected void RaisePropertyChanged(string propName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propName));
}
}
Use this as your ItemsSource:
List<MyTBLViewModel> t_list = db1.GetTable("SELECT * FROM MyTBL LIMIT 4 ORDER BY RANDOM() ;")
.AsEnumerable().Select(entity => new MyTBLViewModel(entity)).ToList();
Now in your view, bind the view elements to "Highlight" and "ItemFontSize", and to any other properties you like:
<ListView.ItemTemplate>
<DataTemplate>
<Grid Margin="6" Background="{Binding Highlight}">
<StackPanel VerticalAlignment="Top" Margin="10,0,0,0">
<TextBlock Name="TB_AMean1" Text="{Binding Entity.AMean1}" TextWrapping="Wrap"
FontSize="{Binding ItemFontSize}"/>
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
Finally, you can get the data item from the SelectionChangedEventArgs -- use it to update your view-related properties:
private void LV_Options_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
foreach (var item in e.AddedItems.OfType<MyTBLViewModel>())
{
item.Highlight = new SolidColorBrush(Color.LightSteelBlue);
item.ItemFontSize = 17;
}
foreach (var item in e.RemovedItems.OfType<MyTBLViewModel>())
{
item.Highlight = new SolidColorBrush(Colors.Transparent);
item.ItemFontSize = 12;
}
}
var item = LV_Options.Items.ElementAt(3);
This line is incorrect. It will not return you a TextBlock. I don't know what a .BackColor is, and it should not compile. The Items property in a ListView will return you a list of ListViewItems. If you want to access the inside element from a ListViewItem, you'll need to access the ContentTemplateRoot property.
Do not use var ever. It lets you assume that you know the type, whereas if you explicitly typed the declaration you would realize you're doing it wrong.
MyTBL wrd = lv1.SelectedItem as MyTBL;
if (wrd == null)
return;
TextBlock tb = lv1.FindName("TB_AMean1") as TextBlock;
What is a MyTBL type? FindName is only available to framework DependencyObjects so I'm assuming it's a user control? You have to provide a lot more code to show us what you're doing and what you're setting the ListView's ItemsSource and ItemTemplate with and what these errors are and how you have 2 breaking debug errors at once and what the error messages are.
Comprehending runtime error messages is a huge part of being a good developer.

Reuse Dynamically created view [duplicate]

This question already has an answer here:
Reusing Text views and Grid
(1 answer)
Closed 8 years ago.
I am dynamically creating say 300 views in For loop :
Ex:
for (int j = 0; j <= 300; j++)
{
Image image = new Image();
image.Source = new BitmapImage(new Uri("/Images/sample256.png", UriKind.RelativeOrAbsolute));
Grid titleGrid = new Grid();
titleGrid.HorizontalAlignment = HorizontalAlignment.Center;
titleGrid.VerticalAlignment = VerticalAlignment.Center;
TextBlock titleText = new TextBlock();
titleText.TextWrapping = TextWrapping.Wrap;
titleGrid.Children.Add(titleText);
Grid subtitleGrid = new Grid();
subtitleGrid.HorizontalAlignment = HorizontalAlignment.Center;
subtitleGrid.VerticalAlignment = VerticalAlignment.Center;
TextBlock subtitleText = new TextBlock();
subtitleText.TextWrapping = TextWrapping.Wrap;
subtitleGrid.Children.Add(subtitleText);
//add all views to root layout
LayoutRoot.Children.Add(image);
LayoutRoot.Children.Add(titleGrid);
LayoutRoot.Children.Add(subtitleGrid);
}
Now there is a lag in the app as I am adding new view each time, how can I reuse the already created views? I am working on Windows Phone 8 app.
adding 300 items in the layout root will definatly make page load slow. you need to use controls that implement virtulization like listbox. here is how
ListBox XAML in your page.
<ListBox Name="myListBox" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Image Source="{Binding ImageUrl}">
</Image>
<TextBlock Text="{Binding Question}"></TextBlock>
<TextBlock Text="{Binding Answer}"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
your code behind
code to bind data
List<MyData> list = new List<MyData>();
for (int i = 0; i < 300; i++)
{
var data = new MyData();
data.Question = "//yourquestion";
data.Answer = "// your answer";
data.ImageSource = new BitmapImage(new Uri("yourimagepat"));
}
myListBox.ItemsSource = list;
Data Class
public class MyData {
public string Question { get; set; }
public string Answer { get; set; }
public BitmapImage ImageSource { get; set; }
}
to take advantage of the virtulization please add your listbox in Grid control. otherwise it can throw out of memory exception and also will be slow
You could try using DataBinding feature instead of creating this .
// You can bound items from your Class here
<ListBox x:Name="ListBox1" Margin="5"
Width="450" Height="200" HorizontalAlignment="Left"
ItemsSource="{Binding SongsList}">
ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel CleanUpVirtualizedItemEvent="VirtualizingStackPanel_CleanUpVirtualizedItemEvent_1">
</VirtualizingStackPanel>
</ItemsPanelTemplate>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="2">
<TextBlock Text="Artist:" Margin="2" />
<TextBlock Text="{Binding Artist}" Margin="2" />
<TextBlock Text="CD:" Margin="10,2,0,2" />
<TextBlock Text="{Binding Name}" Margin="2" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
// your class should be like this
public Songs
{
public string Artist{get;set;}
public string Name {get;set;}
}
// CodeBehind Just Add Data
ObservableCollection<Songs> SongsList=new ObservableCollection<SongsL();
for (int j = 0; j <= 300; j++)
{
SongsList.Add(new Songs{Artist="Aritst Name",Name="Song Name"});
}
// Set this Collection from the codebehind or xaml .
ListBox1.ItemSource=SongsList; // it will the bind the public properties in this Songs.
DataBinding Controls on Windows phone
Msdn Databindin greference
Binding data Grid
Databinding from Jesse Liberty

Binding data in listview itemtemplate using style

I cannot bind my sample data to textblocks in stackpanel, which I defined in resources. I think that I use style in wrong way, because I receive toString() method instead of class binded fields.
That's my resources with defined style:
<UserControl.Resources>
<ItemsPanelTemplate x:Key="VirtualizingStackPanelTemplate">
<VirtualizingStackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
<ListView x:Key="ListBoxTemplate" HorizontalAlignment="Left" ScrollViewer.HorizontalScrollBarVisibility="Visible">
<ListView.ItemTemplate>
<DataTemplate>
<!--<ListBoxItem Background="DarkOrchid" Margin="1,1, 5,5" Height="400" HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch">-->
<StackPanel>
<TextBlock FontSize="30" Text="{Binding Title}"/>
<TextBlock FontSize="20" Text="{Binding Desc}"/>
</StackPanel>
<!--</ListBoxItem>-->
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</UserControl.Resources>
Here is my method in which i add listview programatically:
long rowCount = ContentGridFullView.RowDefinitions.LongCount();
if (rowCount > 8) return;
var c1 = new RowDefinition { Height = new GridLength(1, GridUnitType.Star) };
ContentGridFullView.RowDefinitions.Add(c1);
rowCount = ContentGridFullView.RowDefinitions.LongCount();
TextBlock tb = new TextBlock {Text = "TEXTBLOCK ITEM = " + (rowCount - 1), FontSize = 40};
Viewbox vb = new Viewbox { Child = tb };
if (rowCount > 8) return;
Grid.SetRow(vb, Convert.ToInt32(rowCount-1));
Grid.SetColumn(vb, 1);
ListView lb = new ListView();
lb.Style = Resources["ListBoxTemplate"] as Style;
lb.ItemsPanel = (ItemsPanelTemplate) Resources["VirtualizingStackPanelTemplate"];
var products = new ObservableCollection<Product>() { new Product("ASDASDSADAS", "VCBVCBVCBVCBC"), new Product("ASDASDSADAS", "VCBVCBVCBVCBC"), new Product("ASDASDSADAS", "VCBVCBVCBVCBC"), new Product("ASDASDSADAS", "VCBVCBVCBVCBC") };
lb.ItemsSource = products;
ContentGridFullView.Children.Add(lb);
ContentGridFullView.Children.Add(vb);
Grid.SetRow(lb, Convert.ToInt32(rowCount - 1));
Grid.SetColumn(lb, 2);
And my short class that I want to bind:
public class Product
{
public string Title { get; set; }
public string Desc { get; set; }
public Product(string title, string desc)
{
Title = title;
Desc = desc;
}
public override string ToString()
{
return "I see that message instead of Title and Desc";
}
}
Can someone tell me what's wrong with this code? Thank you.
Create your Observable collection as a property (getter/setter):
ObservableCollection<Product> _products;
public ObservableCollection<Product> products
{
get{return _products;}
set
{
_products=value;
PropertyChanged("products");
}
}
The property changed event will be need to indicate that the collection has changed,its needed when your using ObservableCollection. You'll need to read more about it.You can add items to the products collection by using :
products.Add(Product_object)
And your xaml code will have the itemsSource as follows:
<ListView x:Key="ListBoxTemplate" HorizontalAlignment="Left" ScrollViewer.HorizontalScrollBarVisibility="Visible" ItemsSource="{Binding products}">
<ListView.ItemTemplate>
<DataTemplate>
<!--<ListBoxItem Background="DarkOrchid" Margin="1,1, 5,5" Height="400" HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch">-->
<StackPanel>
<TextBlock FontSize="30" Text="{Binding Title}"/>
<TextBlock FontSize="20" Text="{Binding Desc}"/>
</StackPanel>
<!--</ListBoxItem>-->
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The following statement is important in your xaml code so that your xaml code will know where to look for the data.
DataContext="{Binding RelativeSource={RelativeSource Self}, Path=x}
First try and create a static list and check if data is getting initialized properly and then you can try creating listviews dynamically. But the code above will be the same thing you will have to do create dynamic listviews.

Stackpanel/Itemscontrol Databinding

I have this XAML:
<ItemsControl x:Name="recentSearches"
Margin="0,65,0,0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding q}"
TextWrapping="Wrap"
Foreground="AliceBlue"
Padding="2,6,2,2"
Margin="12,-6,12,0"
FontSize="20" />
</DataTemplate>
</ItemsControl.ItemTemplate>
and this code behind:
private void showLatestSearches()
{
if (fmn.checkLatestSearchesExtistence())
{
List<RecentSearchItem> recent = new List<RecentSearchItem>();
List<String> l = fmn.readLatestSearches();
for (int i = 0; i <= l.Count-1; i += 1)
{
RecentSearchItem r = new RecentSearchItem();
r.q = l[i];
r.generalbg = grau;
recent.Add(r);
}
recentSearches.DataContext = recent;
}
}
the object called fmn reads a .txt from the isolated storage.
But why doesn't anything show up with this StackPanel?
ItemsControl.ItemsSource has to be bound to a collection, for notifications the best would be ObservableCollection<T>.
You are setting the DataContext at the last possible minute, a better way would be to set
DataContext to a ViewModel, could be place where you create your View.
public class Form :UserControl
{
DataContext = new YourViewModel() ;
}
In XAML:
ItemsSource="{Binding SearchesCollection}"
SearchesCollection would be a property in YourViewModel of type ObservableCollection<string>. Whenever you add a new item to SearchesCollection the View updates.
This Databinding Tutorial should help.
Thanks to Lews Therin I managed to finally bind my data to the stackpanel:
<ItemsControl x:Name="recentSearches"
ItemsSource="{Binding recent}"
Background="{Binding generalbg}"
Margin="0,65,0,0" Tap="recentSearches_Tap">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding q}"
Foreground="{Binding foreground}"
TextWrapping="Wrap"
Padding="2,6,2,2"
Margin="12,-6,12,0"
FontSize="20" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
and the code behind:
private void showLatestSearches()
{
if (fmn.checkLatestSearchesExtistence())
{
List<RecentSearchItem> recent = new List<RecentSearchItem>();
List<String> l = fmn.readLatestSearches();
for (int i = 0; i <= l.Count-1; i += 1)
{
RecentSearchItem r = new RecentSearchItem();
r.q = l[i];
r.generalbg = grau;
r.foreground = blau;
recent.Add(r);
}
recentSearches.ItemsSource = recent;
}
}
this works, but unfortunately there seems to be no way to determine, which TextBox is tapped, when one is tapped.

Categories