I have a two classes:
public class ScheduleViewModel : NotificationObject
{
private ObservableCollection<RecordingsCollection> _collection
public ObservableCollection<RecordingsCollection> Collection
{
get { return _collection; }
set
{
_collection= value;
RaisePropertyChanged(() => Collection);
}
}
}
public class RecordingsCollection : NotificationObject
{
private ObservableCollection<Recording> _recordings;
public ObservableCollection<Recording> Recordings
{
get { return _recordings; }
set
{
_recordings = value;
RaisePropertyChanged(() => Recordings);
}
}
}
At the momment I have only dummy data
var a = new ObservableCollection<Recording>();
a.Add(new Recording()
{
Name = "Bla bla",
Schedule = new Schedule()
{
Name = "bla"
}
});
Collection.Add(new RecordingsCollection() { Recordings = a });
var b = new ObservableCollection<Recording>();
b.Add(new Recording()
{
Name = "Bla bla",
Schedule = new Schedule()
{
Name = "bla"
}
});
Collection.Add(new RecordingsCollection() { Recordings = b });
I bind this all to an items control like this
<ItemsControl Grid.Row="1" ItemsSource="{Binding Collection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<telerikGridView:RadGridView
ItemsSource="{Binding ElementName=RecordingDataPager, Path=PagedSource}">
<telerikGridView:RadGridView.Columns>
<telerikGridView:GridViewDataColumn Header="Schedule" DataMemberBinding="{Binding Path=Recordings.Schedule.Name}"/>
</telerikGridView:RadGridView.Columns>
</telerikGridView:RadGridView>
<telerik:RadDataPager x:Name="RecordingDataPager"
Source="{Binding RecordingsCollection, Mode=TwoWay}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Everything is fired fine (i.e. i see two datapagers which means that it sees two entries) except for the get method of the Recordings property in RecordingsCollection
Any ideas?
Edit
Found the issuse... Instead of binding to RecordingsCollection I should have bound to Recordings... Now everything works fine... Hope this helps someone in future :)
This is the answers
<ItemsControl Grid.Row="1" ItemsSource="{Binding Collection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<telerikGridView:RadGridView
ItemsSource="{Binding ElementName=RecordingDataPager, Path=PagedSource}">
<telerikGridView:RadGridView.Columns>
<telerikGridView:GridViewDataColumn Header="Schedule" DataMemberBinding="{Binding Path=Schedule.Name}"/>
</telerikGridView:RadGridView.Columns>
</telerikGridView:RadGridView>
<telerik:RadDataPager x:Name="RecordingDataPager"
Source="{Binding Recordings, Mode=TwoWay}"/>
</Grid>
</DataTemplate>
Related
I have a scenario where I have multiple lists of data that is constructed programmatically in a loop. I want to display these lists side by side on the UI.
I setup a List of ObservableCollections of strings to contain the data. I am using the ListBox way of binding to the lists as shown here: Bind textbox list inside listbox in wpf
with this XMAL:
<ListBox Name="ListTwo" ItemsSource="{Binding Source=obs}" ... >
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Name="TextBoxList" Text="{Binding}" />
</DataTemplate>
</ListBox.ItemTemplate>
The problem is how do you bind a specific listbox to an specific index in the List? Specifically I want the 0th list to bind to List[0], 1st to bind to List[1], etc.
So took the below suggestion and tried to make things into a class. This is what I got, but the UI isn't showing the updates.
XAML:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
x:Class="NS.ClassMainWindow"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Window.Resources>
<ListView Grid.Row="1" Grid.Column="0" x:Name="RawBox" ItemsSource="{Binding Foo.Raw}" Background="LightGray" BorderThickness="2" BorderBrush="Black">
<ListView.ItemTemplate>
<DataTemplate>
<TextBox Name="RawItemsTextBoxList" Text="{Binding}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
DataClass:
public class FooClass
{
public List<ObservableCollection<string>> items;
public ObservableCollection<string> Raw { get => this.items[0]; set => this.items[0] = value; }
public ObservableCollection<string> Tier1 { get => this.items[1]; set => this.items[1] = value; }
public ObservableCollection<string> Tier2 { get => this.items[2]; set => this.items[2] = value; }
public ObservableCollection<string> Tier3 { get => this.items[3]; set => this.items[3] = value; }
public ObservableCollection<string> Tier4 { get => this.items[4]; set => this.items[4] = value; }
public FooClass()
{
this.items = new List<ObservableCollection<string>>();
for (int i = 0; i <= 4; i++)
{
this.items.Add(new ObservableCollection<string>());
}
}
}
And Assignment:
this.Foo.Raw = new ObservableCollection<string>(itemNames); // itemNames is a List<string>
I am very obviously missing something, but for the life of me can't see it. Fairly new to WPF so probably is a noob thing.
If you set the DataContext to an instance of a FooClass and then set the Raw property a non-empty collection like this:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var foo = new FooClass();
foo.Raw = new ObservableCollection<string>(new List<string> { "1", "2", "3" });
DataContext = foo;
}
}
...you should see the strings provided that you bind to the Raw property and set the Mode of the TextBox to either OneTime or OneWay:
<ListView Grid.Row="1" Grid.Column="0" x:Name="RawBox" ItemsSource="{Binding Raw}"
Background="LightGray" BorderThickness="2" BorderBrush="Black">
<ListView.ItemTemplate>
<DataTemplate>
<TextBox Name="RawItemsTextBoxList" Text="{Binding Mode=OneTime}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I have done many searches about this problem but still I can't figure out what is wrong with my project. The flow is like this:
I want to bind a View Model. This view model contains observablecollection that has an observablecollection in it.
Now I can bind to both observablecollections while developing without problems, but when I deploy it, the data inside the other observablecollection isn't show up.
Below is my code:
Project/Model/SubProduct.cs
class SubProducts
{
private string subName;
public string SubName
{
get
{
return subName;
}
set
{
subName = value;
}
}
}
Project/Model/Product.cs
public class Product
{
private string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
private ObservableCollection<SubProducts> subProductsSaProducts;
internal ObservableCollection<SubProducts> SubProductsSaProducts
{
get
{
return subProductsSaProducts;
}
set
{
subProductsSaProducts = value;
}
}
}
Project/Model/Category.cs
class Category
{
private string title;
public string Title
{
get
{
return title;
}
set
{
title = value;
}
}
private ObservableCollection<Product> subProducts;
public ObservableCollection<Product> SubProducts
{
get
{
return subProducts;
}
set
{
subProducts = value;
}
}
}
And this the view model that implements the models:
Project/ViewModel/CategoryViewModel.cs
class CategoryViewModel : ObservableCollection<Category>
{
public CategoryViewModel()
{
ObservableCollection<Product> pCOl1 = new ObservableCollection<Product>();
ObservableCollection<SubProducts> pCol1Sub = new ObservableCollection<SubProducts>();
SubProducts subP1 = new SubProducts();
subP1.SubName = "Lansang";
SubProducts subP2 = new SubProducts();
subP2.SubName = "Lata";
pCol1Sub.Add(subP1);
pCol1Sub.Add(subP2);
Product p1 = new Product();
p1.Name = "Pothaw";
p1.SubProductsSaProducts = pCol1Sub;
pCOl1.Add(p1);
ObservableCollection<Product> pCOl2 = new ObservableCollection<Product>();
Product p2 = new Product();
p2.Name = "Taklob sa COke";
pCOl2.Add(p2);
Add(new Category()
{
Title = "Didang",
SubProducts = pCOl1
});
Add(new Category()
{
Title = "Plastic",
SubProducts = pCOl2
});
}
}
And I use the View model in the xaml wich is the page:
<Page.DataContext>
<vm:CategoryViewModel/>
</Page.DataContext>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<FlipView x:Name="flipView" HorizontalAlignment="Left" VerticalAlignment="Top" Width="360" ItemsSource="{Binding}" Background="#19B0F100">
<FlipView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Foreground="Black" FontSize="30" Text="{Binding Title}"/>
<ListView ItemsSource="{Binding SubProducts}" Background="#FF0C0909" Height="600">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Foreground="Red" FontSize="30" Text="{Binding Name}"/>
<ListView ItemsSource="{Binding SubProductsSaProducts}" Margin="30,0,0,0" Background="#FF933131" Height="197" Width="300">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Foreground="Yellow" FontSize="20" Text="{Binding SubName}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</DataTemplate>
</FlipView.ItemTemplate>
</FlipView>
</Grid>
Now the expected data shows in development mode. In other words, the data shows only when not running the app.
My questions are:
What is wrong with my binding?
What is the proper way to do it?
Why is the data not showing when I run the app?
I'm new to C# WinRT development so any suggestions will be appreciated.
Below is the screenshot:
You should Inherit from Category class not ObservableCollection.
Also I think there's no SubProductsSaProducts property in Category class, as you bind the page to CategoryViewMode which inherit from ObservableCollection
Hi, I am trying to bind the data for text block within a LongListSelector. But I am not getting any Output for it, kindly help me.
This is my XAML code:
<phone:LongListSelector ItemsSource="{Binding ''}" x:Name="longListSelector" HorizontalAlignment="Left" Height="680" VerticalAlignment="Top" Width="446" >
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Name="name" Text="{Binding DataContext.TextContent,ElementName=page,Mode=OneWay}" Height="100" Width="100" HorizontalAlignment="Center">
</TextBlock>
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
In the C# code I have parsed data which i need to display in the windows phone, in a menu format.
Part of C# code is shown below:
XDocument document = XDocument.Parse(e.Result);
var data1 = from query in document.Descendants("location")
select new Data
{
Lat = (string)query.Element("lat"),
Lag = (string)query.Element("lng")
};
foreach (var d in data1)
{
JsonParsing(d.Lat, d.Lag);
}
data1 = from query in document.Descendants("result")
select new Data
{
Country = (string)query.Element("formatted_address")
};
foreach (var d in data1)
{
// ob.JsonParsing(d.Lat, d.Lag);
//XmlParsing(d.Lat, d.Lag);
val = d.Country;
//listbox.Items.Add(val);
//StringsList.Add(val);
TextContent=val;
I want the value of the country to be shown inside the textblock, kindly help me figure this out as I am pretty new to this field, thanks.
try like this
a good reference
<DataTemplate>
<StackPanel VerticalAlignment="Top">
<TextBlock Text="{Binding Value}" />
</StackPanel>
</LongListSelector>
CodeBehind
**Add a public property only public property can be participate in databinding**
#region Public Properties
private ObservableCollection<YourModel> _collectionofValue;
public ObservableCollection<YourModel> CollectionofValues
{
get
{
return _collectionofValue;
}
set
{
_collectionofValue=value;
raisepropertyChanged("CollectionofValues");
}
}
private string _value;
public string Value
{
get
{
return _errorMessage;
}
set
{
_errorMessage = value;
RaisePropertyChanged("Value");
}
}
#endregion
**Set value to this public property when you get value**
// for single values
public void getValue()
{
value =GetXmlValue(); // your method that will return the value;
}
// as it is a collection
public void getValuestoCollection()
{
Collection.Add(new YourModel(value="SampleValue1");
Collection.Add(new YourModel(value="SampleValue1");
Collection.Add(new YourModel(value="SampleValue1");
Collection.Add(new YourModel(value="SampleValue1");
}
YourModel
// the collection of this model is binded to the LongListSelector.
public class ModelName
{
public string Values {get;set;}
}
reference
<phone:LongListSelector ItemsSource="{Binding Items}" x:Name="longListSelector" HorizontalAlignment="Left" Height="680" VerticalAlignment="Top" Width="446" >
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Name="name" Text="{Binding Path=TextContent}" Height="100" Width="100" HorizontalAlignment="Center">
</TextBlock>
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
Your C# algm should be:
i) Have a viewmodel class
public class MyViewModel
{
public ObservableCollection<MyDataItem> Items {get; set;}
public MyViewModel()
{
Items=new ObservableCollection<MyDataItem>();
loop //add your items to your 'Items' property so that you can bind this with LongListSelector ItemsSource
{
Items.Add(new MyDataItem("mystring"));
}
}
}
public class MyDataItem
{
public MyDataItem(string s)
{
TextContent=s;
}
public string TextContent {get;set;}
}
ii) Create an instance to ViewModel class and set DataContext
// write this in the constructor of the page which contains the LongListSelector
public MyViewModel vm;
constructor()
{
vm=new MyViewModel();
this.DataContext=vm;
}
The following is a demo project to show our actual problem.
Suppose we have the following data:
public class Person
{
public PersonType PersonType { get; set; }
public Job Job { get; set; }
}
public class PersonType
{
public string Name { get; set; }
public List<Job> Jobs { get; set; }
}
public class Job
{
public string Name { get; set; }
}
and sample data:
public class TestData
{
public static List<PersonType> PersonTypes = new List<PersonType>
{
new PersonType
{
Name = "Person1",
Jobs = new List<Job>
{
new Job{Name = "Development"},
new Job{Name = "Testing"}
}
},
new PersonType
{
Name = "Person2",
Jobs = new List<Job>
{
new Job{Name = "Design"},
new Job{Name = " Analysis"}
}
}
};
}
Now we have a data grid that is used to view and manage data:
<Window.Resources>
<CollectionViewSource x:Key="People" />
<CollectionViewSource x:Key="PersonTypes" />
<CollectionViewSource x:Key="JobsData" />
</Window.Resources>
<DataGrid ItemsSource="{Binding Source={StaticResource People}}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding PersonType.Name}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox SelectedValue="{Binding PersonType, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding Source={StaticResource PersonTypes}}"
DisplayMemberPath="Name" SelectionChanged="PersonTypeChanged" IsSynchronizedWithCurrentItem="False" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Job.Name}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Source={StaticResource JobsData}}"
DisplayMemberPath="Name" SelectedValue="{Binding Job}" IsSynchronizedWithCurrentItem="False" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
People.Source = new List<Person>();
PersonTypes.Source = TestData.PersonTypes;
}
public CollectionViewSource People { get { return Resources["People"] as CollectionViewSource; } }
public CollectionViewSource PersonTypes { get { return Resources["PersonTypes"] as CollectionViewSource; } }
public CollectionViewSource JobsData { get { return Resources["JobsData"] as CollectionViewSource; } }
private void PersonTypeChanged(object sender, SelectionChangedEventArgs e)
{
var personType = (sender as ComboBox).SelectedItem as PersonType;
if (personType == null)
{
JobsData.Source = null;
}
else
{
JobsData.Source = personType.Jobs;
}
}
}
In short, when the PersonType is selected for a Person row, the Job column should be filled with the possible jobs for that PersonType to choose from.
Now the problem: when we change the 'PersonType' in a row, Job of the other rows will be affected (filtered). It seems that CellEditingTemplate not only applied to editing mode, it is still there and functional, but not shown. So when the ItemsSource of the ComboBox is changed, it will affect all rows.
How can we fix this?
This is happening because you use the same JobsData CollectionViewSource for all the rows. If you don't want to change your design I'd suggest caching the cell editing event and update the JobsData there.
I am binding to a property of an object CaptureNamesList. The variable I need to bind to is a List<string>.
It doesn't work when I bind straight to the List<string>. I created a wrapper class for strings, StringWrapper, and it works when I use the List<StringWrapper> _test4 as a backing variable. However, I need to somehow link this back to _test1. My attempt is shown commented out, but it doesn't seem to work.
How do I bind to this List<string> ?
xaml:
<ItemsControl ItemsSource="{Binding CaptureNamesList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
c#:
public List<StringWrapper> CaptureNamesList
{
get { return _test4; }
set { _test4 = value; }
//get { return StringWrapper.castList(_test1); }
//set { _test1 = StringWrapper.castBackList(value); }
}
private List<StringWrapper> _test4 = StringWrapper.castList(new List<string> { "one", "two" });
private List<string> _test1 = new List<string> { "one", "two" };
The wrapper class for strings:
public class StringWrapper
{
public string Value { get; set; }
static public explicit operator StringWrapper(string value)
{
return new StringWrapper() {Value=value};
}
static public explicit operator string(StringWrapper value)
{
return value.Value;
}
public static List<StringWrapper> castList(List<string> strings)
{
List<StringWrapper> wrappers = new List<StringWrapper>();
strings.ForEach(item => wrappers.Add((StringWrapper)item));
return wrappers;
}
public static List<string> castBackList(List<StringWrapper> wrappers)
{
List<string> strings = new List<string>();
strings.ForEach(item => strings.Add((string)item));
return strings;
}
}
Binding to a List<string> should be exactly the same, except that in your DataTemplate you don't have to specify any property for the binding:
<ItemsControl ItemsSource="{Binding CaptureNamesList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
If you're binding a collection to your XAML, i suggest you use ObservableCollection<string>
public ObservableCollection<string> CaptureNamesList { get; set; }
Im not sure why you'd want to bind a list to a TextBox, maybe what you need is a TextBlock or ListView to show the items in a collection.
<ItemsControl ItemsSource="{Binding CaptureNamesList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Mode=TwoWay}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>