WPF creating multiple groups of controls - c#

Let's say I have five textboxes and five checkboxes next to them.
Now I want to create x groups of controls like that, then bind it with a list of objects that will contain text from textboxes and data on if checkboxes were checked.
What's the common approach for things like that?
I started with writing a function that would loop x times creating new RowDefinition inside an existing Grid, then inside that Row, make another Grid, inside that Grid create five rows and two columns, and add all those controls, set their rows, columns, add binding etc but I think it can't be the right way to do this, it's too much of a hassle writing all of that. There must be a better way.

You can achieve this functionality using a ItemsControl and Defining Datatemplate for the Items. Refer the below code. I taken an example of 3 TextBoxes and Checkboxes.
<StackPanel>
<ItemsControl x:Name="itms">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBox Width="50" Text="{Binding Text1}" Grid.Row="0" Grid.Column="0"/>
<CheckBox IsChecked="{Binding Check1}" Content="Check1" Grid.Row="0" Grid.Column="1"/>
<TextBox Width="50" Text="{Binding Text2}" Grid.Row="1" Grid.Column="0"/>
<CheckBox IsChecked="{Binding Check2}" Content="Check2" Grid.Row="1" Grid.Column="1"/>
<TextBox Width="50" Text="{Binding Text3}" Grid.Row="2" Grid.Column="0"/>
<CheckBox IsChecked="{Binding Check3}" Content="Check3" Grid.Row="2" Grid.Column="1"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Button Click="Button_Click" Content="Add Items"></Button>
</StackPanel>
public partial class Window2 : Window
{
ObservableCollection<MyClass> lst = new ObservableCollection<MyClass>();
public Window2()
{
InitializeComponent();
itms.ItemsSource = lst;
}
int i = 0;
private void Button_Click(object sender, RoutedEventArgs e)
{
i++;
lst.Add(new MyClass() { Text1 = i.ToString(), Text2 =i.ToString()+1,Text3=i.ToString()+2,Check1=true,Check2=true,Check3=false});
}
}
class MyClass
{
public string Text1 { get; set; }
public string Text2 { get; set; }
public string Text3 { get; set; }
public bool Check1 { get; set; }
public bool Check2 { get; set; }
public bool Check3 { get; set; }
}

Related

Why does gridview expand like it has the data, but doesn't display the data?

The data is coming through fine, and I can successfully display the data the in a list box, but when i try to do this in a grid view or list view, i get these results. I feel like something small is missing here.
I've set the two way, and update property source on the textboxes, but still no visible data shown. I know it has the data, because it expands like I captured in this screenshot.
LeadingCauseOfDeath Class
public class LeadingCausesOfDeath : BasePropertyHandler
{
public int Year { get; set; }
public string _113_cause_name { get;set;}
public string Cause_name { get; set; }
public string State { get; set; }
public int Deaths { get; set; }
public int AgeAdjustedDeathRate { get; set; }
}
XAML View
<Grid DataContext="{Binding Source={StaticResource HomePageVM}}">
<StackPanel >
<NavigationView PaneDisplayMode="Top" IsBackButtonVisible="Collapsed" >
<NavigationView.MenuItems>
<NavigationViewItem Content="Family"/>
<NavigationViewItem Content="History"/>
<NavigationViewItem Content="About"/>
</NavigationView.MenuItems>
</NavigationView>
<GridView ItemsSource="{Binding Data, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
IsItemClickEnabled="True"
IsSwipeEnabled="true"
SelectionMode="Single"
BorderThickness="10" BorderBrush="Blue">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid MaximumRowsOrColumns="4" Orientation="Vertical"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemTemplate>
<DataTemplate>
<Grid BorderBrush="Black" BorderThickness="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Cause_name}" />
<TextBlock Grid.Column="1" Text="{Binding Year}" />
<TextBlock Grid.Column="2" Text="{Binding Deaths}" />
<TextBlock Grid.Column="3" Text="{Binding State}" />
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</StackPanel>
</Grid>
View model
private ObservableCollection<LeadingCausesOfDeath> _data;
public ObservableCollection<LeadingCausesOfDeath> Data
{
get
{
return _data;
}
set
{
_data = value;
OnPropertyChanged("Data");
}
}
public HomePageVM()
{
GetData();
}
private async void GetData()
{
var service = new ServiceForApi();
Data = new ObservableCollection<LeadingCausesOfDeath>();
Data = await service.GetFDAStuff();
OnPropertyChanged("Data");
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged( string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Putting a GridView inside a StackPanel is a bad idea. StackPanel will expand as much as it needs to fit the entire content. So, the automatic virtualization that GridView does is lost because it stretches to fit all the items.
With your ItemsWrapGrid's Orientation set to Vertical, it's probably not expanding at all... it expects a fixed height to fill with items and will expand in the horizontal direction.
Use a Grid with two RowDefinitions... first set to Auto, second set to *

Setting button property to invisible in a lisbox based on listitems

I am new to C# and WPF and still learning the ropes. I am currently trying use a ListBox to display some predefined items in a list. I am using an ObservableCollection to hold those items and I am binding that collection to that ListBox. I am also allowing the user to add new items to the list or update selected ones in addition to deleting them. For each item in that list I want to display a DELETE button beside it. However each button should only be visible for the items that have been added by the user and not any of the predefined items.
I am currently able to display the DELETE button for each item in the list. Therefore my question is, is it possible to set the the property of the DELETE button for each item in the list to be visible only for the items that were newly added to it and have no DELETE buttons showing for the predefined(default) items? If so, how would I go about doing that? (That is what I am struggling to figure out.)
Should I post my code?
Thanks
Here is the viewmode which has the list and the controls to add new items to the list.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ListBox x:Name="DrinksListBox" HorizontalAlignment="Center" Height="325" Width="275" Margin="0,0,0,0" VerticalAlignment="Center" Grid.Column="0">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="0,2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Type}" Width="80" Margin="0,0,10,0" Grid.Column="0"/>
<TextBlock Text="{Binding Name}" Width="80" Margin="0,0,10,0" Grid.Column="1" HorizontalAlignment="Left"/>
<Button x:Name="DrinkDeleteButton" Content="Delete" Click="CmdDeleteDrink_Clicked" HorizontalAlignment="Right" Grid.Column="2"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBox x:Name="DrinkNameTextBox" Grid.Column="1" HorizontalAlignment="Left" Height="45" Margin="0,0,0,100" TextWrapping="Wrap" Text="Enter Drink Name" VerticalAlignment="Center" Width="240" FontSize="20" VerticalContentAlignment="Center"/>
<ComboBox x:Name="DrinkTypeComboBox" Grid.Column="1" HorizontalAlignment="Left" Margin="0,47,0,0" VerticalAlignment="Top" Width="240" Height="45" ItemsSource="{Binding Drinks, Mode=OneWay}" DisplayMemberPath="Type" FontSize="20"/>
<Button x:Name="AddDrinkButton" Content="Add Drink" Grid.Column="1" HorizontalAlignment="Right" Margin="0,0,10,100" VerticalAlignment="Center" Width="100" Height="45" Click="CmdAddDrink_Clicked"/>
</Grid>
Here is my code-behind. I have a inner class for the drink property and the main class that sets up the list to be used.
public partial class MainWindow : Window
{
public ObservableCollection<Drinks> Drinks { get; private set; }
public MainWindow()
{
InitializeComponent();
Drinks = new ObservableCollection<Drinks>();
Drinks.Add(new Drinks("Soda", "Pepsi"));
Drinks.Add(new Drinks("Tea", "Lemon"));
Drinks.Add(new Drinks("Caffinated", "Coffee"));
Drinks.Add(new Drinks("Other", "Water"));
DrinksListBox.ItemsSource = Drinks;
DrinkTypeComboBox.ItemsSource = Drinks;
}
private void CmdDeleteDrink_Clicked(object sender, RoutedEventArgs e)
{
Button cmd = (Button)sender;
if (cmd.DataContext is Drinks deleteDrink)
{
Drinks.Remove(deleteDrink);
}
}
private void CmdAddDrink_Clicked(object sender, RoutedEventArgs e)
{
string typeSelection = ((Drinks)DrinkTypeComboBox.SelectedItem).Type;
Drinks.Add(new Drinks(typeSelection, DrinkNameTextBox.Text));
}
}
Drink class has the type of drink and a name for it.
public class Drinks
{
private string type;
private string name;
public Drinks(string type, string name)
{
this.type = type;
this.name = name;
}
public string Type
{
get { return type; }
set
{
if (type != value)
{
type = value;
}
}
}
public string Name
{
get { return name; }
set
{
if (name != value)
{
name = value;
}
}
}
}
Let's say you have your item:
public class Drinks
{
//your properties, simplified for clarity
public string Name {get;set;}
public string Type {get;set;}
//hey, a new one!
public bool IsUserDefined {get;set;}
}
Then, when the user adds one:
private void CmdAddDrink_Clicked(object sender, RoutedEventArgs e)
{
string typeSelection = ((Drinks)DrinkTypeComboBox.SelectedItem).Type;
Drinks.Add(new Drinks(typeSelection, DrinkNameTextBox.Text)
{
IsUserDefined = true
});
}
disclaimer: from the top of my head; normally that means syntax errors; removed some parts for clarity.
<!-- In your resources section of the XAML -->
<BooleanToVisibilityConverter x:Key="BoolToVis" />
<ListBox x:Name="DrinksListBox" ItemSource="{Binding Drinks}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Type}"/>
<TextBlock Text="{Binding Name}"/>
<Button x:Name="DrinkDeleteButton"
Visibility="{Binding Path=IsUserDefined,
Converter={StaticResource BoolToVis}}"/>
<!-- note: left out some attributes for clarity -->
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
That should do the trick.
Btw, you seem to be mixing some typical MVVM style coding and code-behind coding. It's worth to say that you might benefit by using a ViewModel in your code.

WPF MultiColumn ListBox showing index

i have a multicolumn ListBox as you can see below.
<ListBox x:Name="lstQuestions" HorizontalAlignment="Left" Height="544" VerticalAlignment="Top" Width="175" Margin="0,0,0,-0.5" SelectionChanged="lstQuestions_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="0,2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding qID}"/>
<Image Source="{Binding imgPath}" Width="140" Height="50" Stretch="UniformToFill" Grid.Column="1"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I want to show the index number (like 1, 2, 3 ...) instead of <TextBlock Text="{Binding qID}"/> in first column, how can I do that?
Edit: Binding code behind
public class QList
{
public string qID { get; set; }
public string imgPath { get; set; }
public int ansCount { get; set; }
public string rightAns { get; set; }
}
and
public static List<QList> questions = new List<QList>();
last one
lstQuestions.ItemsSource = Test.questions;
The first two are in a class called Test

How to make datepicker in MVVM treeview WPF

I have a pretty complex question:
At my work, we use WPF with MVVM standards.
On one of our UserControls, there is a treeview that loads all the tables from the database. For each table, the name is loaded in the list by the treeview. When you click on the table name, you can add data to that table from the screen.
Basically, it loads the column names from the table on the side, and lets you enter data and save. The records are then saved and added as children to the table. From here, selecting a child lets you update that info.
Now, the current app loads the data fine. The table names and data are loaded. The child data loads.
Everything is fine, but when it comes to loading the controls, we only use Textboxes.
On the usercontrol the code is:
<UserControl.Resources>
<ResourceDictionary>
<DataTemplate x:Key="AdditionalItemsTemplate">
<Border>
<StackPanel>
<Label
Content="{Binding Name}"
Style="{StaticResource PanelLabelStyle}"/>
<TextBox
Text="{Binding Value}"
Style="{StaticResource TextBoxStyle}"/>
</StackPanel>
</Border>
</DataTemplate>
</ResourceDictionary>
</UserControl.Resources>
<Border
Height="350"
Width="{Binding Width}"
Style="{StaticResource InnerMenuBorderStyle}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Border
Grid.Row="0"
Grid.Column="0"
Width="230"
IsEnabled="{Binding IsUpdateEnabled}">
<StackPanel>
<Border
Margin="3,3,3,0"
Style="{StaticResource PanelBorderStyle}">
<StackPanel>
<Label Style="{StaticResource PanelLabelStyle}">
<TextBlock
Text="{Binding TableName}"
TextWrapping="WrapWithOverflow"/>
</Label>
<TextBox
Style="{StaticResource TextBoxStyle}"
Text="{Binding Value}"
TextWrapping="Wrap"/>
<ItemsControl
Width="222"
HorizontalAlignment="Left"
ItemsSource="{Binding additionalFields}" Margin="0,0,-226,0"
ItemTemplate="{StaticResource AdditionalItemsTemplate}"/>
</StackPanel>
</Border>
<Button
Width="70"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Margin="3.5,0,0,0"
Template="{StaticResource UpdateButtonTemplate}"
Command="{Binding ButtonCommand}"
CommandParameter="Update"/>
</StackPanel>
</Border>
<Rectangle
Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="1"
HorizontalAlignment="Left"
VerticalAlignment="Stretch"
Width="2"
StrokeDashArray="0.5 1.0 0.3"
Stroke="LightGray"
Visibility="{Binding IsAddVisible}"/>
<Border
Grid.Row="0"
Grid.Column="2"
Width="230"
Visibility="{Binding IsAddVisible}">
<StackPanel>
<Border
Margin="3,3,3,0"
Style="{StaticResource PanelBorderStyle}">
<StackPanel>
<Label
Grid.Row="0"
Content="{Binding LabelText}"
Style="{StaticResource PanelLabelStyle}"/>
<TextBox
Grid.Row="1"
Text="{Binding NewLookup}"
Style="{StaticResource TextBoxStyle}"/>
<ItemsControl
Width="222"
Margin="0,0,-226,0"
HorizontalAlignment="Left"
ItemsSource="{Binding childAdditionalFields}"
ItemTemplate="{StaticResource AdditionalItemsTemplate}"/>
</StackPanel>
</Border>
<Button
Grid.Row="2"
Width="50"
HorizontalAlignment="Left"
Margin="3.5,0,0,0"
Template="{StaticResource AddButtonTemplate}"
Command="{Binding ButtonCommand}"
CommandParameter="Add"/>
</StackPanel>
</Border>
</Grid>
</Border>
In the resources, the AdditionalItemsTemplate loads a label for each column name, and the textbox is loaded with the values, or can be used to enter new values
I would like to make just ONE datepicker for ONE table.
So for example. In table Students, the fields are Name (varchar), Age (varchar), DateStarted (date). A textbox loads for Name and Age, but just for DateStarted a datepicker should load.
So far, in the resources, i add <local:DatePicker
SelectedDate="{Binding Value}"
Visibility="{Binding DateVisible}"/>
So that when the table Student is loaded, the visibility of the datepicker is changed from being hidden to visible.
Here is a sample of the ViewModel:
public AddUpdateConfigurationViewModel(TreeViewContainer treeViewContainer, List<AddChangeSiteConfigurationViewModel> lookupTypeList, FieldDataResponse fieldDataResponse)
{
NewLookup = String.Empty;
Width = 480;
DateVisible = "Hidden";
IsAddVisible = "Hidden";
IsUpdateEnabled = false;
if (treeViewContainer.AdditionalFields != null)
{
if (treeViewContainer.AdditionalFields.Count() > 0)
{
treeViewContainer.AdditionalFields.RemoveAll(x => x.Name.Contains("ID"));
treeViewContainer.AdditionalFields.RemoveAll(x => x.Name.Contains("Guid"));
}
}
if (treeViewContainer.AdditionalFields != null)
this.additionalFields = new ObservableCollection<TreeViewContainer>(treeViewContainer.AdditionalFields);
if ((treeViewContainer.ParentTable == null) | (treeViewContainer.ParentTable == String.Empty))
IsUpdateEnabled = true;
var lookupTypes = lookupTypeList.Where(x => x.Parent_Field == "ID" + treeViewContainer.TableName);
if (treeViewContainer.ParentTable == "IsParent")
{
IsAddVisible = "Visible";
DateVisible = "Hidden";
LabelText = "New " + treeViewContainer.Name;
TableName = treeViewContainer.TableName;
childAdditionalFields = new ObservableCollection<TreeViewContainer>();
foreach (var additionalField in treeViewContainer.AdditionalFields)
childAdditionalFields.Add(new TreeViewContainer(additionalField.Name));
if (treeViewContainer.Name.Equals("Student"))
{
DateVisible = "Visible";
}
}
else if (lookupTypes.Count() > 0)
{
foreach (var lookupType in lookupTypes)
{
IsAddVisible = "Visible";
LabelText = "New " + lookupType.Name;
TableName = lookupType.TableName;
childAdditionalFields = new ObservableCollection<TreeViewContainer>();
foreach (var additionalChildField in lookupType.additionalFieldsDictionary)
childAdditionalFields.Add(new TreeViewContainer(additionalChildField.Key));
}
}
else
Width = 250;
this.Name = treeViewContainer.Name;
this.Value = treeViewContainer.Name;
this.ID = treeViewContainer.ID;
this.treeViewContainer = treeViewContainer;
this.lookupTypeList = lookupTypeList;
this.fieldDataResponse = fieldDataResponse;
}
I hope this makes sense.
Now when i load the usercontrol and select on another table, sometimes the datepicker is visible, even though the visibility is set to Hidden.
And when the Student table is selected, there are datepickers under textboxes for every field.
How do I go about just making one datepicker for this one table?
If there is any more info needed, I will edit and update accordingly
EDIT
Screenshots
This is how the treeview loads. all the tables in the db are listed here
now clicking on a table that shouldn't have the datepicker does this:
it adds the datepicker to this treeview container. i want to eliminate this,
and this is where it should be
but i have too many, see. there should only be one added here. not all the way down, under every textbox.
and the Visible setting is just a temp fix, until i get this datepicker sorted. the visibility can be tackled later
I don't think adding a datepicker and trying to show/hide it is the best way to go. A better way is to load a datatemplate which matches the type which is being bound to. So if the column is a datetime type, you should load a datatemplate which has a label and a datepicker. This is what the DataTemplateSelector is for. You create a class which extends DataTemplateSelector, and decide which template to return, based on the object being bound to.
<UserControl.Resources>
<DataTemplate x:Key="DateTimeFieldTemplate">
<Border>
<StackPanel>
<Label
Content="{Binding Name}"
Style="{StaticResource PanelLabelStyle}"/>
<local:DatePicker
SelectedDate="{Binding Value}"/>
</StackPanel>
</Border>
</DataTemplate>
<DataTemplate x:Key="TextFieldTemplate">
<Border>
<StackPanel>
<Label
Content="{Binding Name}"
Style="{StaticResource PanelLabelStyle}"/>
<TextBox
Text="{Binding Value}"
Style="{StaticResource TextBoxStyle}"/>
</StackPanel>
</Border>
</DataTemplate>
<local:TemplateSelector x:Key="TemplateSelector" DateTimeFieldTemplate="{StaticResource DateTimeFieldTemplate}" TextFieldTemplate="{StaticResource TextFieldTemplate}"/>
</UserControl.Resources>
<Grid>
<ItemsControl ItemsSource="{Binding Items}" ItemTemplateSelector="{StaticResource TemplateSelector}"/>
</Grid>
You illustrate in your original code that you have a Name and Value property, so you only need to decide on how to provide information on what datatype the Value property is. One way is to make an interface with a Value property of type object:
public interface IBoundDataColumn
{
public string Name { get; } // Not really necessary for the template selector, but perhaps for completeness
public object Value { get; }
}
public class DateTimeColumn : IBoundDataColumn
{
public string Name { get; set; }
public object Value { get; set; }
}
public class TemplateSelector : DataTemplateSelector
{
public DataTemplate TextFieldTemplate
{
get;
set;
}
public DataTemplate DateTimeFieldTemplate
{
get;
set;
}
public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)
{
IBoundDataColumn boundCol = item as IBoundDataColumn;
if (boundCol.Value.GetType() == typeof(DateTime))
{
return DateTimeFieldTemplate;
}
else
{
return TextFieldTemplate;
}
return base.SelectTemplate(item, container);
}
}
Or you could have a DataType property:
public interface IBoundDataColumn
{
public Type DataType {get;}
}
public class DateTimeColumn : IBoundDataColumn
{
public string Name {get;set;}
public DateTime Value {get;set;}
public Type DataType { get { return typeof(DateTime); } }
}
Or you could avoid the interface altogether and use reflection to get the type dynamically:
public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)
{
var p = item.GetType().GetProperty("Value");
if (t.PropertyType == typeof(DateTime))
...
}

ListBox not databinding

My ListBox control is working fine, except that the data to be bound is not displaying.
My XAML:
<ListBox x:Name="listFileNames" SelectionMode="Single" Margin="10">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Image Margin="5" Source="{Binding Path=Image}" Stretch="Fill" Width="50" Height="50"></Image>
<StackPanel Grid.Column="1" Margin="5">
<TextBlock Text="{Binding Path=FileName}" FontWeight="Bold"></TextBlock>
<TextBlock Text="{Binding Path=State}"></TextBlock>
<TextBlock Text="This text shows..."></TextBlock>
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
My code:
public struct StyleDocumentFile
{
public string Image;
public string FileName;
public string State;
}
// ......
StyleDocumentFile sdf = new StyleDocumentFile()
{
Image = "/Images/Loading.png",
FileName = "abc",
State = "Extracting Data...",
};
this.listFileNames.Items.Add(sdf);
Change fields to Property. After this, all works fine.
public struct StyleDocumentFile
{
public string Image { get; set; }
public string FileName { get; set; }
public string State { get; set; }
}
You should set ItemsSource in ListBox definition like ItemsSource="{Binding Model.Items}". In addition you must call RaisePropertyChanged in setter of model properties.

Categories