ObservableCollection binding does not work as expected [duplicate] - c#

This question already has answers here:
Why does WPF support binding to properties of an object, but not fields?
(2 answers)
Closed 4 years ago.
I have a problem with binding ObservableCollections. Other properties (string) are OK. Here is my code:
MainWindow.xaml
<StackPanel>
<TextBlock Text="{Binding Title}"/>
<ItemsControl ItemsSource="{Binding Data}">
<TextBlock Text="{Binding B}"/>
</ItemsControl>
</StackPanel>
MainWindow.xaml.cs
public MainWindow()
{
InitializeComponent();
DataContext = new MainWindowVm();
}
MainWindowVm
class MainWindowVm
{
public ObservableCollection<A> Data;
public string Title { get; set; } = "HELLO WORLD";
public MainWindowVm()
{
Data = new ObservableCollection<A>() {new A() {B = "X"}, new A() {B = "X"}};
}
}
class A
{
public string B { get; set; }
}
Result
What am I doing wrong?

OK, as others already mentioned, you need to change the Data field into a property.
public ObservableCollection<A> Data { get; set; }
To get rid of the error
Items collection must be empty before using ItemsSource.
Change your XAML to:
<StackPanel>
<TextBlock Text="{Binding Title}"/>
<ItemsControl ItemsSource="{Binding Data}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding B}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>

Related

WPF: Expander binding in Listview

I want to ListView with expander including some of information. So, I made this code. I'm not sure binding expander like that is correct. I just try to Binding like ListViewItem, But when I try to expander is not work at all. Here is my code.
XAML :
<Grid Grid.Row="2">
<ListView x:Name="lv">
<ListView.Template>
<ControlTemplate>
<HeaderedItemsControl>
<ItemsPresenter/>
</HeaderedItemsControl>
</ControlTemplate>
</ListView.Template>
<ListView.ItemTemplate>
<DataTemplate DataType="{x:Type local:LogBase}">
<Expander Grid.Column="0" HorizontalAlignment="Center">
<Expander.HeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal"> <!-- why this code is not wokring...? -->
<TextBlock Text="{Binding No}"/>
<TextBlock Text="{Binding Timestamp}"/>
<TextBlock Text="{Binding Type}"/>
</StackPanel>
</DataTemplate>
</Expander.HeaderTemplate>
</Expander>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
code behind :
public partial class MainWindow : Window
{
public List<LogBase> logs { get; set; }
public MainWindow()
{
InitializeComponent();
logs = new List<LogBase>();
logs.Add(new LogBase()
{
No = "1",
Timestamp = "123456789",
Type = "Tcp"
});
logs.Add(new LogBase()
{
No = "2",
Timestamp = "123456789",
Type = "Tcp"
});
logs.Add(new LogBase()
{
No = "3",
Timestamp = "123456789",
Type = "Tcp"
});
lv.ItemsSource = logs;
DataContext = this;
}
}
public class LogBase
{
public string No { get; set; }
public string Timestamp { get; set; }
public string Type { get; set; }
}
for better understanding I captured what I want to
Now my program's situation
If you have any of opinions please comment for me!
You also need to bind the header to set the DataContext of the HeaderTemplate correct. This is done by Header="{Binding HeaderSource}". In your case just use Header="{Binding}" to bind directly to the item:
<Expander Header="{Binding}>
After that your code works perfectly.

Invalid binding path 'MyStatic' : Property 'MyStatic' can't be found on type 'CreatePage' [duplicate]

This question already has answers here:
Update Listview with Object Data
(1 answer)
Static binding doesn't update when resource changes
(2 answers)
Closed 6 years ago.
So I've been looking for the wright solution for my problem. It seems I'm not able to bind to a observableCollection that is located in my models folder. I am able to add items in it and in a later stadium retrieve these with some C# Code. BUT I just can't seem to bind to the items from a page I named CreatePage.
I keep getting this message: Invalid binding path 'Questionlist' : Property 'Questionlist' can't be found on type 'CreatePage'.
Class with the observableCollection:
public partial class MyStatic
{
static MyStatic()
{
Questionlist = new ObservableCollection<QuestionList>();
}
public static ObservableCollection<QuestionList> Questionlist;
}
public class QuestionList
{
public string Question { get; set; }
public string Answer { get; set; }
public string Delete { get; set; }
public string Correct { get; set; }
public string Wrong { get; set; }
public string UserAnswer { get; set; }
}
This is my Xaml:
<ScrollViewer Grid.Row="4"
Grid.ColumnSpan="2"
Margin="20,10"
MaxWidth="650">
<RelativePanel>
<ListView Name="Questionviewlist"
ItemsSource="{x:Bind Questionlist}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="data:QuestionList">
<TextBlock Name="Questionview"
Text="{x:Bind Question}"
TextWrapping="Wrap"
FontFamily="Arial Rounded MT Bold"
FontWeight="Bold"
Foreground="Brown"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ListView Name="Answerviewlist"
RelativePanel.AlignHorizontalCenterWithPanel="True"
ItemsSource="{x:Bind Questionlist}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="data:QuestionList">
<TextBlock Name="Answerview"
Text="{x:Bind Answer}"
FontFamily="Arial Rounded MT Bold"
FontWeight="Bold"
Foreground="Brown"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ListView Name="Deleteviewlist"
RelativePanel.AlignRightWithPanel="True"
ItemsSource="{x:Bind Questionlist}"
IsItemClickEnabled="True"
ItemClick="Deleteviewlist_ItemClick">
<ListView.ItemTemplate>
<DataTemplate x:DataType="data:QuestionList">
<TextBlock Name="Deleteview"
Text="{x:Bind Delete}"
TextWrapping="WrapWholeWords"
Foreground="#FFB57C"
FontStyle="Italic"
FontFamily="Arial Rounded MT Bold"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</RelativePanel>
</ScrollViewer>

Dynamically Create Controls in MVVM

I am pretty new to WPF. I am trying to create controls dynamically in MVVM but controls are not rendered on view. I want some number of label and textbox to be created on view.
Below is my code:
Model Code
public class MyModel
{
public string KeyName
{
get;
set;
}
public string KeyValue
{
get;
set;
}
}
ModelView Code
public class MyViewModel
{
private ObservableCollection<MyModel> propertiesList = new ObservableCollection<MyModel>();
public CustomWriterViewModel()
{
GetMyProperties()
}
public ObservableCollection<MyModel> Properties
{
get { return propertiesList; }
}
private void GetMyProperties()
{
MyModel m = new MyModel();
m.KeyName = "Test Key";
m.KeyValue = "Test Value";
MyModel.Add(m);
}
}
View Code(Which is user control)
<Grid>
<ItemsControl ItemsSource="{Binding Properties}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type cw:MyModel}">
<StackPanel Orientation="Horizontal">
<Label Margin="10" Content="{Binding Properties.KeyName}"></Label>
<TextBox Margin="10" Text="{Binding Properties.KeyValue}" Width="250"></TextBox>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
When view renders, I can only see empty textbox. I cannot understand what is wrong..?
As per my comment:
The DataTemplate receives an individual item as its DataContext, therefore you only need to include item level property names within your binding paths like:
<DataTemplate DataType="{x:Type cw:MyModel}">
<StackPanel Orientation="Horizontal">
<Label Margin="10" Content="{Binding KeyName}"></Label>
<TextBox Margin="10" Text="{Binding KeyValue}" Width="250"></TextBox>
</StackPanel>
</DataTemplate>

How generate(binding) quiz in form using wpf mvvm

How binding quiz with different type questions in WPF app using MVVM?
QuizPageViewModel:
public class QuizPageViewModel : ViewModelBase
{
public QuizPageViewModel()
{
QuizCollection = new ObservableCollection<QuizQuestion>();
}
public ObservableCollection<QuizQuestion> QuizCollection { get; set; }}
Where QuizQuestion: - EF Entity
public partial class QuizQuestion
{
public QuizQuestion()
{
QuizAnswers = new HashSet<QuizAnswer>();
QuizMultiQuestions = new HashSet<QuizMultiQuestion>();
}
public long Id { get; set; }
public int QuizId { get; set; }
***public String Type { get; set; }***
[Required]
public string Name { get; set; }
}
Question Type can be truefalse, multianswer, multichoice and other type
in xaml:
<ItemsControl ItemsSource="{Binding QuizCollection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ListBox ItemsSource="{Binding Path=QuizAnswers}"
VerticalAlignment="Stretch"
Background="Transparent">
<ListBox.ItemTemplate>
<ItemContainerTemplate>
<RadioButton GroupName="{Binding Id}"
Content="{Binding Name}" />
</ItemContainerTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
this xaml code display only radiobutton question of quiz. How binding and display other Type of question (checkbox, combobox, textbox)? HELP)))
You can use an Item template selector in your items control to display different controls/templates depending on the question.
In the code below you can see that there's a conditional statement that checks the type of question and return a template based on the type of question.
public class QuiztemplateSelector : DataTemplateSelector
{
public DataTemplate TrueOrFalseTemplate { get; set; }
public DataTemplate MultiAnswerTemplate { get; set; }
public DataTemplate MultiChoiceTemplate { get; set; }
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
var question = item as QuizQuestion;
if (question.Type.Equals("TruOrFalse"))
return TrueOrFalseTemplate;
else if (question.Type.Equals("MultiAnswer"))
return MultiAnswerTemplate;
else if ("MultiChoice")
return MultiChoiceTemplate;
return null; //Or your default Template.
}
}
Now in your xaml, you can create templates for the types of questions (i.e. true/False, Multi choice, multi answer). Then you need to pass those templates to the QuiztemplateSelector as shown below.
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.Resources>
<DataTemplate x:Key="TrueOrFalse">
<!-- Write your True or false template here-->
</DataTemplate>
<DataTemplate x:Key="MultiChoice">
<!-- Write your MultiChoice template here-->
</DataTemplate>
<DataTemplate x:Key="MultiAnswer">
<!-- Write your multianswer Template here -->
</DataTemplate>
<local:QuizTemplateSelector x:Key="QuizTemplateSelector"
MultiAnswerTemplate="{StaticResource MultiAnswer}"
TrueOrFalseTemplate="{StaticResource TrueOrFalse}"
MultiChoiceTemplate="{StaticResource MultiChoice}" />
</Grid.Resources>
<ItemsControl ItemsSource="{Binding QuizCollection}" ItemTemplateSelector="{StaticResource QuiztemplateSelector}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ListBox ItemsSource="{Binding Path=QuizAnswers}"
VerticalAlignment="Stretch"
Background="Transparent">
<ListBox.ItemTemplate>
<ItemContainerTemplate>
<RadioButton GroupName="{Binding Id}"
Content="{Binding Name}" />
</ItemContainerTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
You can read more abour DataTemplateSelector here.

How to bind imported ObservableCollection of strings to ItemsControl

example
class abc
{
public ObservableCollection<string> Data { get; set; }
//data will be initialized in some functions
}
and wpf application
namespace WpfApplication
{
public partial class MainWindow : Window
{
[Import(typeof(GateManager))]
public abc _abc { get; set; }
public MainWindow()
{
InitializeComponent();
}
}
public void OnImportsSatisfied()
{
var binding = new Binding
{
Source = _abc,
Path = new PropertyPath("Data")
};
databox.SetBinding(ItemsControl.SourceProperty, binding);
//databox is name of the ItemControl like //<ItemsControl x:Name="databox" ScrollViewer.VerticalScrollBarVisibility="Auto">
// <ItemsControl.ItemTemplate>
// <DataTemplate>
// <StackPanel Orientation="Horizontal">
// <TextBlock Text="{Binding}" />
// </StackPanel>
// </DataTemplate>
//</ItemsControl.ItemTemplate>
//</ItemsControl> }
}
}
Im trying to do like this but this is not working
Add DataContext also
<Window.DataContext>
<ViewModel:ManageUserViewModel/>
</Window.DataContext>
in cs file :
private ObservableCollection<UserType> _listUserTypes = new ObservableCollection<UserType>();
public ObservableCollection<UserType> UserTypes
{
set
{
_listUserTypes = value;
}
get
{
return _listUserTypes;
}
}
In Xaml:
<ItemsControl ItemsSource="{Binding Path=UserTypes, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
public List<string> Data { get; set; }
in XAML,
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
You want to set the ItemSource to the instance of an ObservableCollection you created in the constructor:
YourItemsControL.ItemsSource = Data ;

Categories

Resources