I am trying to bind a dictionary to two textblocks in a listview. The listview ItemsSource binding is defined in the code behind and the text blocks content is in the XAML.
I am able to display the items but they are displayed with square brackets around each row like [stringA, stringB]. However, this format will not work. The latest code that I tried was by setting the Key and Value which did not work was:
XAML:
<ListView Name="lvListLogs"
Margin="0,10,0,0">
<ListView.ItemTemplate>
<DataTemplate x:Name="ListItemTemplate">
<Grid Margin="5,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="122"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition MaxHeight="104"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock x:Name="tb_PointName" Grid.Column="1"
Text="{Binding Key}"
Margin="10,0,0,0" FontSize="40"
TextWrapping="Wrap"
MaxHeight="72"
Foreground="#FFFE5815" />
<TextBlock x:Name="tb_PointValue" Grid.Column="1"
Text="{Binding Value}"
Margin="10,0,0,0" FontSize="40"
TextWrapping="Wrap"
MaxHeight="72"
Foreground="#FFFE5815" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
C# (abridged for clarity):
public Dictionary<string, string> mydict2 { get; set; }
mydict2 = new Dictionary<string, string>();
if (item != null)
{
var props = item.GetType().GetRuntimeProperties();
foreach (var prop in props)
{
foreach (var itm in group1.Items.Where(x => x.UniqueId == prop.Name))
{
var _Title = prop.Name;
var _Value = prop.GetValue(item, null);
string propertyValue;
string propertyName;
propertyValue = Convert.ToString(_Value);
propertyName = _Title;
mydict2.Add(_Title, propertyValue);
}
}
//binding here
lvListLogs.ItemsSource = mydict2;
}
Any assistance would be appreciated.
Your code works fine, the problem is you set the same Grid.Column for both TextBlocks. The first column index should be zero:
<TextBlock x:Name="tb_PointName" Grid.Column="0" ...
To achieve the required binding, instead of the Dictionary I used an ObservableCollection with the class and constructor.
To databind the listview (xaml) to ObservableCollection:
Create the Class with Constructor
public class PointInfoClass
{
public string PointName { get; set; }
public string PointValue { get; set; }
public PointInfoClass(string pointname, string pointvalue)
{
PointName = pointname;
PointValue = pointvalue;
}
}
Create collection of the PointInfoClass
public ObservableCollection<PointInfoClass> PointInfo
{
get
{
return returnPointInfo;
}
}
Instantiate the collection
ObservableCollection<PointInfoClass> returnPointInfo = new ObservableCollection<PointInfoClass>();
Add item to collection
returnPointInfo.Add(new PointInfoClass(string1, string2));
Databind to the ObservableCollection name.
The xaml code:
<ListView
Grid.Row="1"
ItemsSource="{Binding PointInfo}"
IsItemClickEnabled="True"
ItemClick="ItemView_ItemClick"
Margin="19,0.5,22,-0.333"
x:Name="lvPointInfo"
Background="White">
<ListView.ItemTemplate>
<DataTemplate >
<Grid Margin="0,0,0,20">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="270"/>
<ColumnDefinition Width="60"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical" Grid.Column="1" VerticalAlignment="Top">
<TextBlock x:Name="tb_PointSubTitle" Grid.Column="1"
Text="{Binding PointName}"
Margin="10,0,0,0" FontSize="20"
TextWrapping="Wrap"
MaxHeight="72"
Foreground="#FF5B5B5B"
/>
</StackPanel>
<StackPanel Orientation="Vertical" Grid.Column="2" VerticalAlignment="Top" HorizontalAlignment="Right">
<TextBlock x:Name="tb_PointValue"
Grid.Column="1"
Text="{Binding PointValue}"
Margin="0,5,0,0" FontSize="20"
HorizontalAlignment="Right"
TextWrapping="Wrap"
FontWeight="Normal"
Foreground="Black" />
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Set the DataContext of the ListView
lvPointInfo.DataContext = this;
This code is edited for clarity.
Related
I'm learning wpf through mvvm.
My application consist of below logic.
Form which has a button that will add a selected components horizontally from Itemcontrol like textbox, combobox and rich textbox and a button whenever the button is clicked.
When the add button is clicked the specified set of components will be added in the line information dynamically.
2) Data will be inserted into the table after pressing the add info button.
3) The issue is after clicking the add info button, the components in the itemscontrol should be readonly. This is the place I'm struggling as of now.
Model.cs:
public class textboxModel
{
public string Text { get; set; }
public string lblText { get; set; }
public string isactive { get; set; }
public bool txtboxreadonly { get; set; }
}
public class ButtonDataModel
{
public string Content { get; set; }
public ICommand Command { get; set; }
public string column { get; set; }
public string isactive { get; set; }
public bool buttreadonly { get; set; }
}
ViewModel.cs:
public class viewmodel : notifyproperties
{
public Relaycommand Status { get; set; }
public Relaycommand AddCommand { get; set; }
public labelconversionOnPauseButtonclick pauseclick = new labelconversionOnPauseButtonclick();
public auditinformation auditid = new auditinformation();
public ButtonDataModel bdm = new ButtonDataModel();
public auditinformation adt
{
get { return auditid; }
set
{
if (value != auditid)
{
auditid = value;
OnPropertyChanged("adt");
}
}
}
public labelconversionOnPauseButtonclick res
{
get { return pauseclick; }
set
{
if (value != pauseclick)
{
pauseclick = value;
OnPropertyChanged("res");
}
}
}
public viewmodel()
{
Status = new Relaycommand(pauseclick.Statusdata);
AddCommand = new Relaycommand(o => auditid.addcommand());
}
}
public class auditinformation : notifyproperties
{
public Relaycommand Command { get; set; }
private string _lines;
public string Lines
{
get { return this._lines; }
set
{
this._lines = value;
this.OnPropertyChanged("Lines");
}
}
private readonly ObservableCollection<ButtonDataModel> _MyDatabutton = new ObservableCollection<ButtonDataModel>();
public ObservableCollection<ButtonDataModel> MyData { get { return _MyDatabutton; } }
private readonly ObservableCollection<textboxModel> _MyDatatxtbox = new ObservableCollection<textboxModel>();
public ObservableCollection<textboxModel> MyDatatxtbox { get { return _MyDatatxtbox; } }
private readonly ObservableCollection<LabelDataModel> _MyDataLabel = new ObservableCollection<LabelDataModel>();
public ObservableCollection<LabelDataModel> MyDataLabel { get { return _MyDataLabel; } }
public void addcommand()
{
int num= 1;
for (int i = 0; i < num; i++)
{
MyDatatxtbox.Add(new textboxModel
{
isactive = "1",
});
MyData.Add(new ButtonDataModel
{
Command = new Relaycommand(o => search()),
Content = "Add info",
isactive = "1",
});
}
}
public void search( )
{
var asss = MyDatatxtbox.Where(a=> a.isactive == "1").Select(a => a.Text);
var itemstoremove = MyDatatxtbox.Where(i => i.isactive == "1").ToList();
foreach (var s in asss)
{
foreach (var a in itemstoremove)
{
if (a.isactive == "1")
{
MessageBox.Show(s);
buttreadonly = true;
}
}
}
// var itemstoremove = MyDatatxtbox.Where(i => i.isactive == "1").ToList();
foreach(var a in itemstoremove)
{
a.isactive = "0";
}
//foreach (var a in itemstoremove)
//{
// a.txtboxreadonly = true;
//}
// var itemstoremovebutton = MyData.Where(i => i.isactive == "1").ToList();
// foreach (var a in itemstoremovebutton)
// {
//// MyData.Remove(a);
// a.isactive = "0";
// }
}
}
window.xaml:
<GroupBox Header="Audit Information" Grid.Row="1">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="0" Text="Member ID"></TextBlock>
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="1" Width="85" ></TextBox>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="2" Text="Claim Number"></TextBlock>
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="3" Width="85" ></TextBox>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="4" Text="Date Audited"></TextBlock>
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="5" Width="85" ></TextBox>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="6" Text="Query ID"></TextBlock>
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="7" Width="85" ></TextBox>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="8" Text="Audit ID"></TextBlock>
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="9" Width="85" ></TextBox>
<Button HorizontalAlignment="Center" VerticalAlignment="Center" Width="85" Height="25" Command="{Binding AddCommand}" Content="Add" Grid.Column="10"></Button>
</Grid>
</GroupBox>
<GroupBox Grid.Row="2" Margin="0,0,0,0" Header="Line Information" >
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="3.2*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="1.8*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Height="22" Grid.Column="0">
<Label HorizontalAlignment="Center" Content="DOS" />
</StackPanel>
<ItemsControl Grid.Column="0" Grid.Row="1" ItemsSource="{Binding adt.MyDatatxtbox}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,50">
<TextBox IsReadOnly="{Binding txtboxreadonly}" Text="{Binding Text, Mode=TwoWay}" Height="25" Width="85" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Height="22" Grid.Column="1">
<Label HorizontalAlignment="Center" Content="CPT" />
</StackPanel>
<ItemsControl Grid.Column="1" Grid.Row="1" ItemsSource="{Binding adt.MyDatatxtbox}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,50">
<TextBox IsReadOnly="{Binding txtboxreadonly}" Margin="0,0,30,0" Text="{Binding Text, Mode=TwoWay}" Height="25" Width="85" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Height="22" Grid.Column="2">
<Label HorizontalAlignment="Right" Content="Open-close Modifier" Margin="0,0,-17,0" Width="121" />
</StackPanel>
<ItemsControl Grid.Column="2" Grid.Row="1" ItemsSource="{Binding adt.MyDatatxtbox}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,50">
<TextBox IsReadOnly="{Binding txtboxreadonly}" Margin="0,0,30,0" Text="{Binding Text, Mode=TwoWay}" Height="25" Width="85" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Height="22" Grid.Column="3">
<Label HorizontalAlignment="Center" Content="Comments" />
</StackPanel>
<ItemsControl Grid.Column="3" Grid.Row="1" ItemsSource="{Binding adt.MyDatatxtbox}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,10">
<RichTextBox IsReadOnly="{Binding txtboxreadonly}" Margin="0,0,0,0" Height="65" Width="425" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Height="22" Grid.Column="4">
<Label HorizontalAlignment="Center" Content="Line Status" />
</StackPanel>
<ItemsControl Grid.Column="4" Grid.Row="1" ItemsSource="{Binding adt.MyDatatxtbox}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="10,0,0,50">
<ComboBox IsEnabled= "{Binding txtboxreadonly}" Margin="0,0,0,0" Height="25" Width="95" >
<ComboBoxItem Content="Coffie"></ComboBoxItem>
<ComboBoxItem Content="Tea"></ComboBoxItem>
</ComboBox>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Height="22" Grid.Column="5">
<Label HorizontalAlignment="Center" Content="Additional Comments" />
</StackPanel>
<ItemsControl Grid.Column="5" Grid.Row="1" ItemsSource="{Binding adt.MyDatatxtbox}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,10">
<RichTextBox IsReadOnly="{Binding txtboxreadonly}" Margin="0,0,0,0" Height="65" Width="425" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ItemsControl Grid.Column="6" Grid.Row="1" ItemsSource="{Binding adt.MyData}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,50">
<Button Margin="0,0,0,0" Height="25" Width="55" Content="{Binding Content}" Command="{Binding Command}" >
</Button>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</ScrollViewer>
</GroupBox>
</Grid>
</Grid>
</TabItem>
</TabControl>
So the question is how to disable/readonly the Line Information ,textbox and cpt on add info button click.
Dirty way would be adding a "global" bool property in your ViewModel and binding it to your Controls IsEnabled/ReadOnly Properties.
I have a nested listview. When clicks on it's button I want to get it's row index. Now I got the index as -1 always.
<ListView x:Name="Mainlist" HorizontalAlignment="Stretch">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:CurrentBooksList">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" ></ColumnDefinition>
</Grid.ColumnDefinitions>
<ListView x:Name="sublist1" ItemsSource="{x:Bind CurrentFoldersArray}" Grid.Column="0" BorderBrush="Black" BorderThickness="0,0,0,1" HorizontalAlignment="Stretch" >
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:CurrentFoldersList">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Foreground="Black" FontWeight="Bold" Grid.Column="0" TextWrapping="Wrap" HorizontalAlignment="Left" VerticalAlignment="Center" Text="{x:Bind BookCode}"/>
<ListView x:Name="sublist2" ItemsSource="{x:Bind CurrentBookArray1}" Grid.Column="1" HorizontalAlignment="Stretch" >
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:CurrentBusList1">
<Button Width="120" Height="40" Text="{x:Bind Lockbook}" Click="LockMyBook_btn_Click">
</Button>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
private void LockMyBook_btn_Click(object sender, RoutedEventArgs e)
{
int selectedIndx = Mainlist.SelectedIndex; //always return -1
}
How can I get the row number of mainlist view, when user clicks on it's inner listview's button?
Yes it runs well. By getting row number of mainlist, I want to access corresponding items in CurrentBooksList
Well, it's strange. If you're using a basic UWP button control, it doesn't have Text property, your code should not work. But I didn't care about this point, your question was not related to it.
In your button's click event handler, you could get its DataContext, then you could convert it to an CurrentBusList1 object. By this CurrentBusList1 object, you could do some judgements from your 'Mainlist' ItemsSource and get the selected CurrentBooksList object.
public sealed partial class MainPage : Page
{
public ObservableCollection<CurrentBooksList> currentBooksLists { get; set; }
public MainPage()
{
this.InitializeComponent();
currentBooksLists = new ObservableCollection<CurrentBooksList>();
ObservableCollection<CurrentFoldersList> currentFoldersLists = new ObservableCollection<CurrentFoldersList>();
currentFoldersLists.Add(new CurrentFoldersList() { BookCode = "abc123", CurrentBookArray1 = new ObservableCollection<CurrentBusList1>() { new CurrentBusList1() { Lockbook = "123abc" }, new CurrentBusList1() { Lockbook = "123def" } } });
currentFoldersLists.Add(new CurrentFoldersList() { BookCode = "def456", CurrentBookArray1 = new ObservableCollection<CurrentBusList1>() { new CurrentBusList1() { Lockbook = "def456" } } });
currentBooksLists.Add(new CurrentBooksList() { CurrentFoldersArray = currentFoldersLists });
}
private void Button_Click(object sender, RoutedEventArgs e)
{
int index;
var subSelectedItem = ((FrameworkElement)sender).DataContext as CurrentBusList1;
foreach (var item in currentBooksLists)
{
foreach (var folder in item.CurrentFoldersArray)
{
foreach (var bus in folder.CurrentBookArray1)
{
if (bus == subSelectedItem)
{
index = currentBooksLists.IndexOf(item);
break;
}
}
}
}
}
}
public class CurrentBooksList
{
public ObservableCollection<CurrentFoldersList> CurrentFoldersArray { get; set; }
}
public class CurrentFoldersList
{
public string BookCode { get; set; }
public ObservableCollection<CurrentBusList1> CurrentBookArray1 { get; set; }
}
public class CurrentBusList1
{
public string Lockbook { get; set; }
}
<ListView x:Name="Mainlist" HorizontalAlignment="Stretch" ItemsSource="{x:Bind currentBooksLists}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:CurrentBooksList">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" ></ColumnDefinition>
</Grid.ColumnDefinitions>
<ListView x:Name="sublist1" ItemsSource="{x:Bind CurrentFoldersArray}" Grid.Column="0" BorderBrush="Black" BorderThickness="0,0,0,1" HorizontalAlignment="Stretch" >
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:CurrentFoldersList">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Foreground="Black" FontWeight="Bold" Grid.Column="0" TextWrapping="Wrap" HorizontalAlignment="Left" VerticalAlignment="Center" Text="{x:Bind BookCode}"/>
<ListView x:Name="sublist2" ItemsSource="{x:Bind CurrentBookArray1}" Grid.Column="1" HorizontalAlignment="Stretch" >
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:CurrentBusList1">
<Button Width="120" Height="40" Content="{x:Bind Lockbook}" Click="Button_Click">
</Button>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I have class
public class Clip
{
public string ID { get; set; }
public string Name { get; set; }
public int? Duration { get; set; }
}
And ObservableCollection
public ObservableCollection<Clip> _clipsFound;
public ObservableCollection<Clip> collection
{
get { return _clipsFound; }
set
{
_clipsFound = value;
OnPropertyChanged();
}
}
OnPropertyChanged() is invoked when I do
_clipsFound = collection
I want binding data from collection to ListBox with three columns: ID, Name, Duration
Initialize
ID = id;
collection = new ObservableCollection<Clip>();
_clipsFound = collection;
_clipsFound.Clear();
ICollection<Clip> ClipF = await Service.GetClips(ID);
ICollection<Clip> Clipcol = ClipF;
collection = new ObservableCollection<Clip>(Clipcol);
I try do this, but it doesn't work
<ListBox Grid.Row="2" ItemsSource="{Binding collection}" BorderBrush="Transparent" >
<ListBox.ItemTemplate>
<DataTemplate DataType="ui:Clip">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Text="{Binding Title}"
VerticalAlignment="Center"
HorizontalAlignment="Left"
TextTrimming="CharacterEllipsis"
Foreground="#FF4F4F4F"
FontSize="12"
Margin="55 0 0 0"/>
<TextBlock Grid.Column="1"
Margin="0 0 45 0"
Text="{Binding Duration}"
VerticalAlignment="Center"
HorizontalAlignment="Right"
FontSize="11"
Foreground="#FF4F4F4F"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
What did I do wrong?
You cannot send data from viewmodel to view without setting DataContext. DataContext is like channel or bridge between ViewModel and View.
This code sets DataContext:
<Window.DataContext>
<vm:MainWindowViewModel />
</Window.DataContext>
Let's see work example:
Your ViewModel:
public class MainWindowViewModel
{
publicMainWindowViewModel
{
LoadData();
}
private void LoadData()
{
_clipsFound=new ObservableCollection<Clip>();
for(int startIndex=0; startIndex<10; startIndex++)
{
collection.Add(new Clip(){ID=startIndex, Name="Bob", Duration=startIndex++});
}
}
public ObservableCollection<Clip> _clipsFound;
public ObservableCollection<Clip> collection
{
get
{
return _clipsFound;
}
set
{
_clipsFound = value;
}
}
}
Your XAML:
<Window x:Class="DataGridSelectedItemsWpfApplication.MainWindow"
...The code omitted for the brevity...
xmlns:vm="clr-namespace:DataGridSelectedItemsWpfApplication.ViewModel"
Title="MainWindow" WindowStartupLocation="CenterScreen" Height="550" Width="525">
<Window.DataContext>
<vm:MainWindowViewModel />
</Window.DataContext>
<ListBox Grid.Row="2" ItemsSource="{Binding collection}" BorderBrush="Transparent" >
<ListBox.ItemTemplate>
<DataTemplate DataType="ui:Clip">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding ID}" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="11" Margin="2" Foreground="#FF4F4F4F"/>
<TextBlock Grid.Column="1" Margin="2" Text="{Binding Name}" VerticalAlignment="Center" HorizontalAlignment="Center" TextTrimming="CharacterEllipsis" Foreground="#FF4F4F4F" FontSize="12"/>
<TextBlock Grid.Column="2" Margin="2" Text="{Binding Duration}" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="11" Foreground="#FF4F4F4F"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Window>
There are many ways to set DataContext.
Im trying to learn how to make datatemplate in listviews in my win 8 app
I have the following code in my Xaml code
<!-- Vertical scrolling item list -->
<ListView x:Name="itemListView"
Margin="120,0,0,60"
ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
SelectionChanged="ItemListView_SelectionChanged">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Height="110" Margin="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" Width="110" Height="110">
<Image Source="{Binding Image}" Stretch="UniformToFill"/>
</Border>
<StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,0,0,0">
<TextBlock Text="{Binding Title}" TextWrapping="NoWrap" FontFamily="Global User Interface"/>
<TextBlock Text="{Binding Subtitle}" TextWrapping="NoWrap"/>
<TextBlock Text="{Binding Description}" MaxHeight="60" FontFamily="Global User Interface"/>
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
What I cant work out is how to set the text for the three text blocks Title,Subtitle & Description as well as the Picture in Image
Usually When the page loads I use the following in my itemListView_Loaded(object sender, RoutedEventArgs e) method
itemListView.Items.Add(Convert.ToString(correct) + ". " + line.Split(',')[6]);
But how do I do it Im really stumped
Any help appreciated
Mark
You'll have to make a class which includes those properties.
public class MyItem
{
public string Title { get; set; }
public string Subtitle { get; set; }
public string Description { get; set; }
public string Source { get; set; }
}
Then when you add items:
var item = new MyItem();
item.Title = "Title";
item.Subtitle = "Subtitle";
item.Description = "Some example description.";
item.Source = "Assets/SomeFolder/SomeImage.png";
itemListView.Items.Add(item);
That worked in my app (AirPett Transit)
So I'm having what should be a simple XAML Data Binding error. I've got the below XAML with two classes (so far) that they used for DataBinding, a Row, which contains an ObservableCollection rows. The nodes have a bunch of extra associated information and I'm trying to show these nodes in a grid-like fashion (it's going to be used for a path-finding algorithm.)
The problem is that the "Here" TextBlock doesn't show up. But I know that the Nodes are getting bound properly because their values show up in the Debugging StackPanel.
<Window.Resources>
<local:Row x:Key="TestRow">
<local:Node x="0" y="0" Cost="20" />
<local:Node x="0" y="1" Cost="20" />
<local:Node x="0" y="2" Cost="20" />
</local:Row>
</Window.Resources>
<Grid Name="MainGrid" Margin="10,10,10,10" >
<Grid.RowDefinitions>
<RowDefinition Height="150" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<StackPanel Margin="0,25,0,0"
DataContext="{Binding ElementName=AStarListView,
Path=SelectedItem}"
x:Name="Debugging" Orientation="Vertical" >
<TextBlock Text="{Binding x}" />
<TextBlock Text="{Binding y}" />
<TextBlock Text="{Binding Cost}" />
</StackPanel>
<ListView Grid.RowSpan="2" Margin="2,2,2,2" Grid.Column="1"
x:Name="AStarListView"
ItemsSource="{StaticResource TestRow}" >
<ListView.ItemTemplate>
<DataTemplate DataType="local:Row">
<ListView ItemsSource="{Binding nodes}" Width="48" Height="48" >
<ListView.ItemTemplate>
<DataTemplate DataType="local:Node">
<TextBlock Text="Here" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Here's the (stripped) Node class.
public class Node : INotifyPropertyChanged
{
public Tuple<int, int> coordinates { get; set; }
public int x
{
get
{
if (this.coordinates == null)
return -1;
return this.coordinates.Item1;
}
set
{
if (this.coordinates != null)
this.coordinates = new Tuple<int, int>(value, y);
else
this.coordinates = new Tuple<int, int>(value, -1);
OnPropertyChanged("x");
}
}
public int y
{
get
{
if (this.coordinates == null)
return -1;
return this.coordinates.Item2;
}
set
{
if (this.coordinates != null)
this.coordinates = new Tuple<int, int>(x, value);
else
this.coordinates = new Tuple<int, int>(-1, value);
OnPropertyChanged("y");
}
}
private Node _parent;
private int _Cost;
public int Cost
{
get
{
return _Cost;
}
set
{
_Cost = value;
OnPropertyChanged("Cost");
}
}
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChangedEventArgs args =
new PropertyChangedEventArgs(propertyName);
this.PropertyChanged(this, args);
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
Here's the Row class:
public class Row : ObservableCollection<Node>
{
public ObservableCollection<Node> nodes { get; set; }
public Row()
{
this.nodes = new ObservableCollection<Node>();
}
}
Here's the corrected XAML, the class definitions are correct in the question, need to replace "AStarListView" with this XAML.
<ListView Grid.RowSpan="2" Margin="2,2,2,2" Grid.Column="1" x:Name="AStarListView"
ItemsSource="{StaticResource TestRow}" >
<ListView.ItemTemplate>
<DataTemplate DataType="local:Node">
<Grid Background="#dddddd" >
<TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding x}"/>
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding y}"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="{Binding Cost}"/>
<Grid.RowDefinitions>
<RowDefinition Height="24"/>
<RowDefinition Height="24"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24"/>
<ColumnDefinition Width="24"/>
</Grid.ColumnDefinitions>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
My problem was that I had the ListViews too deeply nested. The inner ListView was binding to the "nodes" property of a Node, which didn't exist.