I am struggling last days to achieve following layout:
I have a ListBox with template for each Item:
Label always anchored on left side
Label always anchored on right side
Label (TextBlock) in middle with flexible size
3rd label bellow, so far this is easiest to set :)
Main problem in my example is that I can't made middle text (that can be long) to adjust, but not push suffix (red) label while I am resizing ListBox.
I hope that this layout is possible, and that I am missing something trivial.
What's interesting is that 1st example (bellow) work well "outside" listbox. Do I need somehow force realign of listbox while resizing?
Thanks for any help.
I have attached bellow 2 examples I tried (beside many other):
XAML:
<Window x:Class="WPF_Experiments.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPF_Experiments"
mc:Ignorable="d"
Title="MainWindow" Height="400" Width="400">
<Window.Resources>
<DataTemplate x:Key="Template1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Foreground="Blue" Background="Aqua" Content="{Binding Prefix}" />
<Label Grid.Column="1" Content="{Binding Description}" />
<Label Grid.Column="2" Foreground="Magenta" Background="Beige" Content="{Binding Suffix}" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="Template2">
<DockPanel LastChildFill="True">
<Label Grid.Column="0" Foreground="Blue" Background="Aqua" Content="{Binding Prefix}" />
<Label Grid.Column="2" DockPanel.Dock="Right" Foreground="Magenta" Background="Beige" Content="{Binding Suffix}" />
<TextBlock Grid.Column="1" Text="{Binding Description}" TextTrimming="CharacterEllipsis" />
</DockPanel>
</DataTemplate>
</Window.Resources>
<StackPanel>
<ListBox Name="MyListBox"
ItemTemplate="{DynamicResource Template2}"/>
</StackPanel>
</Window>
C#:
namespace WPF_Experiments
{
class Item
{
public string Prefix { get; set; }
public string Description { get; set; }
public string Suffix { get; set; }
}
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
List<Item> items = new List<Item>();
items.Add(new Item() { Prefix = "001", Description = "Item 0", Suffix = "cm" });
items.Add(new Item() { Prefix = "002", Description = "This is very long item that maybe will not fit", Suffix = "in" });
items.Add(new Item() { Prefix = "003", Description = "Item 2", Suffix = "m" });
MyListBox.ItemsSource = items;
}
}
}
(Edit) One more try with StackPanel:
<DataTemplate x:Key="Template3">
<StackPanel Orientation="Horizontal">
<Label Foreground="Blue" Background="Aqua" Content="{Binding Prefix}" />
<TextBlock Text="{Binding Description}" TextTrimming="CharacterEllipsis" />
<Label Foreground="Magenta" Background="Beige" Content="{Binding Suffix}" HorizontalAlignment="Right" />
</StackPanel>
</DataTemplate>
You can achieve this by disabling horizontal scrolling for ListBox:
<ListBox Name="MyListBox" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ItemTemplate="{DynamicResource Template2}"/>
Related
I am trying to insert several StackPanel inside the WrapPanel as you can see the XAML below:
Only the TextBlock inside the StackPanel will be modified so as not to repeat the Title and Text.
<Window x:Class="ambient_test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ambient_test"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<ScrollViewer CanContentScroll="True">
<WrapPanel x:Name="wrappanel">
<StackPanel x:Name="panel1" Width="120" Margin="5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="120"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Background="#FF38C59F"></StackPanel>
<TextBlock Grid.Row="2" Text="Title 1" Foreground="LightGray" VerticalAlignment="Top" TextAlignment="Center"/>
<TextBlock Grid.Row="1" Text="Text 1" Foreground="#FF747474" TextAlignment="Center" Margin="0 15 0 0"/>
</Grid>
</StackPanel>
<StackPanel x:Name="panel2" Width="120" Margin="5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="120"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Background="#FF38C59F"></StackPanel>
<TextBlock Grid.Row="2" Text="Title 2" Foreground="LightGray" VerticalAlignment="Top" TextAlignment="Center"/>
<TextBlock Grid.Row="1" Text="Text 2" Foreground="#FF747474" TextAlignment="Center" Margin="0 15 0 0"/>
</Grid>
</StackPanel>
</WrapPanel>
</ScrollViewer>
</Grid>
</Window>
I created a class called Info to change the Title and the Text. In the method constructor I have a for loop that will add 10 contents to the List.
public MainWindow()
{
InitializeComponent();
List<Info> infos = new List<Info>();
for (int i = 0; i < 10; i++)
{
infos.Add(new Info()
{
Title = $"title {i}",
Text = $"text {i}"
});
}
}
public class Info
{
public string Title { get; set; }
public string Text { get; set; }
}
For example, my List has 100 records, so I need to add 100 StackPanel inside my WrapPanel following the same Title and Text as the List.
Is there any way to do this? For example using Binding?
You would use an ItemsControl that uses a WrapPanel as its ItemsPanel, and defines the layout of the items by an appropriate DataTemplate:
<ItemsControl x:Name="itemsControl">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="120"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding Title}" .../>
<TextBlock Grid.Row="1" Text="{Binding Text}" .../>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
and assign the List<Info> to its ItemsSource property:
itemsControl.ItemsSource = infos;
I have a list box bound to an observable object in my ViewModel. When the user selects an item in the listbox the SelectedItem fires the "SelectedSandwich" property. The value is saved to a private field. The properties SandwichName and Description are properties of the Sandwich object. I want text blocks in my view to show selected sandwichname and price, but I don't want to bind these text blocks to the listbox element.
Here is the view:
'
<Window.DataContext>
<vm:SandwichVM/>
</Window.DataContext>
<Window.Resources>
<DataTemplate x:Key="lstSandwich">
<Border BorderThickness="3"
CornerRadius="4"
HorizontalAlignment="Stretch"
BorderBrush="Blue">
<TextBlock HorizontalAlignment="Stretch">
<Run Text="{Binding SandwichName}"/>
<Run Text=" | " />
<Run Text="{Binding Description}" />
<Run Text=" | " />
<Run Text="{Binding Price}" />
</TextBlock>
</Border>
</DataTemplate>
<DataTemplate x:Key="menu" >
<Border>
<TextBlock HorizontalAlignment="Stretch">
<Run Text="{Binding SandwichName}"/>
<Run Text="{Binding Price}" />
</TextBlock>
</Border>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="2*"/>
</Grid.RowDefinitions>
<ListBox Grid.Row="0" x:Name="cboMenu"
ItemsSource="{Binding Sandwiches}"
SelectedItem="{Binding SelectedSandwich, Mode=TwoWay}"
ItemTemplate="{StaticResource lstSandwich}"
Margin="3">
</ListBox>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontStretch="ExtraExpanded"
FontFamily="Verdana"
FontSize="22"
>
<Run Text="Your Selection"/>
</TextBlock>
<Grid Grid.Row="1">
<ContentControl
ContentTemplate="{StaticResource menu}"
HorizontalAlignment="Stretch"
Margin="5,0,5,0">
</ContentControl>
</Grid>
</Grid>
</Grid>
</Window>'
Here is the ViewModel:
'class SandwichVM : INotifyPropertyChanged
{
private Sandwich _selectedSandwich;
private ObservableCollection<Sandwich> _sandwiches;
public ObservableCollection<Sandwich> Sandwiches
{
get { return _sandwiches; }
}
public SandwichVM()
{
//fake data for the list
_sandwiches = new ObservableCollection<Sandwich>();
_sandwiches.Add(new Sandwich("Pastrami", "Stacked high on rye bread with a touch of mustard.", 8.50));
_sandwiches.Add(new Sandwich("Tuna", "Fresh tuna salad on wheat with slice of cheddar cheese.", 6.50));
_sandwiches.Add(new Sandwich("Steak", "Sliced grilled steak with sauteed mushrooms and onions.", 9.50));
_sandwiches.Add(new Sandwich("Chicken Salad", "Juicy chunks of chicken breast, onions, fruit.", 6.50));
_sandwiches.Add(new Sandwich("Buffalo Chicken", "Caliente! Fried chicken breast slathered with hot buffalo wing sauce.", 8.50));
_sandwiches.Add(new Sandwich("Tofu", "I don't know how to make a tofu sandwich.", 1.50));
}
public Sandwich SelectedSandwich
{
get { return _selectedSandwich; }
set
{
if (_selectedSandwich != value)
{
_selectedSandwich = value;
RaisePropertyChangedEvent("SelectedSandwich");
}
}
}
public string SandwichName
{
get { return _selectedSandwich.SandwichName; }
set
{
_selectedSandwich.SandwichName = value;
RaisePropertyChangedEvent("SandwichName");
}
}
public string Description
{
get { return _selectedSandwich.Description; }
set
{
_selectedSandwich.Description = value;
RaisePropertyChangedEvent("Description");
}
}
public string Price
{
get { return _selectedSandwich.Price.ToString(); }
set
{
_selectedSandwich.Price = Convert.ToDouble(value);
RaisePropertyChangedEvent("Price");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChangedEvent(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}'
I tried putting the RaisePropertyChangedEvent in the setters for the three properties (though I only need to read them) but the setters are never executed. In fact, the setter for the SelectedSandwich property is never executed. The get is executed everytime. I have stepped through the code but can't see where the problem lies.
Thank you for your help.
Maybe its not clear to me, but the only property you are setting from UI is the SelectedSandwich property. If it sets properly when you change the selected listbox item then why not to bind to the SelectedSandwich from the other place?
So if you want some text blocks in your view to show selected sandwichname and price just try something like:
<TextBlock Text="{Binding SelectedSandwich.Name}"/>
<TextBlock Text="{Binding SelectedSandwich.Price}"/>
Or if you want to use your prepared datatemplate:
<DataTemplate DataType="{x:Type sandwichVMNamespace:Sandwich}">
<Border>
<TextBlock HorizontalAlignment="Stretch">
<Run Text="{Binding SandwichName}"/>
<Run Text="{Binding Price}" />
</TextBlock>
</Border>
</DataTemplate>
<Grid Grid.Row="1">
<ContentControl
Content="{Binding SelectedSandwich}"
HorizontalAlignment="Stretch"
Margin="5,0,5,0">
</ContentControl>
</Grid>
And you are done...
I am working on windows phone app where I need to get the latest streams from a site. I currently made a custom control that can hold each item from JSON:
<UserControl x:Class="TwitchStationApp.StreamItem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
d:DesignHeight="195" d:DesignWidth="480">
<Grid x:Name="LayoutRoot" Height="195" Width="469">
<Image Height="156" HorizontalAlignment="Left" Margin="12,12,0,0" Name="imageChannel" Stretch="Fill" VerticalAlignment="Top" Width="156" />
<TextBlock Height="84" HorizontalAlignment="Left" Margin="174,48,0,0" Name="textBlockStatus" Text="TextBlock" VerticalAlignment="Top" Width="294" />
<TextBlock Height="30" HorizontalAlignment="Left" Margin="174,12,0,0" Name="textBlockChanelName" Text="TextBlock" VerticalAlignment="Top" Width="294" Foreground="#FFB0CB3E" />
<TextBlock Height="30" HorizontalAlignment="Left" Margin="174,138,0,0" Name="textBlockViewers" Text="TextBlock" VerticalAlignment="Top" Width="294" />
</Grid>
</UserControl>
So I will make a list of items List<Stream> _stream = new ..... So this list will be populated by lets say 10 items. For each item I need to make a User control (above) and add it to the ListBox so that users can scroll and select (click/tap) on the item they want to get more information about.
What is the best way to do this? I checked microsoft website and there is something about having ItemTemplate in a XAML file in <Window.Resource> tag but I dont know where and how to create this file and link it to the listbox I have.
This is typically done using a data template.
Assuming you have a collection of StreamTypes
public class StreamType
{
public string Title { get; set; }
public string Description { get; set; }
}
You can define a Data template in
Application wide – in app.xaml
Page Scope – on the page
Control container scope – local to the container of the listbox
Within the Listbox itself
To define it page wide:
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="SharedStreamTemplate">
<StackPanel>
<TextBlock FontSize="{StaticResource PhoneFontSizeExtraLarge}" Text="{Binding Title}" />
<TextBlock FontSize="{StaticResource PhoneFontSizeExtraLarge}" Text="{Binding Description}" />
</StackPanel>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
In your list box, assign the data template to the item template
<ListBox x:Name="lstStreams" ItemTemplate="{StaticResource SharedStreamTemplate}" />
If there isn't a plausible cause for you to re-use the template, just assign it directly in the listbox
<ListBox x:Name="lstStreams">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock FontSize="{StaticResource PhoneFontSizeExtraLarge}" Text="{Binding Title}" />
<TextBlock FontSize="{StaticResource PhoneFontSizeExtraLarge}" Text="{Binding Description}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Update
In your code behind
// Constructor
public MainPage()
{
InitializeComponent();
BindStreams();
}
private void BindStreams()
{
lstStreams.ItemsSource = new List<StreamType>
{
new StreamType { Description = "Description One", Title = "Title One"},
new StreamType { Description = "Description Two", Title = "Title Two"},
new StreamType { Description = "Description Three", Title = "Title Three"},
};
}
That's right you need to use the ItemsControl.ItemTemplate property. Using this property, you can specify a template that will be applied to each item in the list. Here's sample code:
Model:
public class Model
{
public string Name { get; set; }
public Guid Id { get; set; }
}
XAML
<ListBox ItemsSource="{Binding Path=MyItemsSource}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=Name}"/>
<TextBlock Text="{Binding Path=Id}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I am working on a WPF app where I need to dynamically create GroupBoxes(which contains combobxes, sliders and togglebutton) based on Button Click. I have two xaml files in my View Folder. 'CodecView.xaml' and 'CodecWidgetView.xaml'.
CodecView.XAML:
<Grid>
<ScrollViewer Name="GroupBoxScroll" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0" >
<Grid Name="NumberofCodecs" Style="{DynamicResource styleBackground}" />
</ScrollViewer>
</Grid>
<Button Content="Add Box" Name="AddBoxBtn" Command="{Binding AddGroupBoxCommand}" />
CodecWidgetView.xaml:
<GroupBox Header="{Binding GroupBoxHeader}" Height="Auto" HorizontalAlignment="Stretch" Margin="5,5,0,0" Name="groupBox1" VerticalAlignment="Stretch" Width="Auto">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ToggleButton Name="FrequencyBox" Content="Master" Grid.Column="1" Height="25" Width="50" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0" />
<ComboBox Grid.Column="2" Height="23" HorizontalAlignment="Center" Margin="0,0,0,0" Name="comboBox2" VerticalAlignment="Center" Width="80" />
<ComboBox Grid.Column="0" Height="23" HorizontalAlignment="Center" Margin="0,0,0,0" Name="comboBox1" VerticalAlignment="Center" Width="80" />
</Grid>
s
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ToggleButton Name="OneSixBit" Content="16 Bit" Grid.Column="0" Height="25" Width="45" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0" />
<ToggleButton Name="ThreeTwoBit" Content="32 Bit" Grid.Column="3" Height="25" Width="45" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0" />
<ToggleButton Name="TwentyBit" Content="20 Bit" Grid.Column="1" Height="25" Width="45" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0" />
<ToggleButton Name="TwentyFourBit" Content="24 Bit" Grid.Column="2" Height="25" Width="45" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0" />
</Grid>
<Grid Grid.Row="2">
<Label Name="BitDelay" Content="Bit Delay" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,205,0" Height="25" Width="55" />
<Slider Height="23" HorizontalAlignment="Center" Minimum="0.0" Maximum="255.0" TickFrequency="1.0" Margin="95,0,0,0" Name="bitdelayslider" VerticalAlignment="Center" Width="160" />
<TextBox Name="BitDelayValue" IsReadOnly="True" Text="{Binding ElementName=bitdelayslider,Path=Value}" Width="40" Height="20" Margin="0,0,110,0" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
<Grid Grid.Row="3">
<Label Name="DBGain" Content="DB Gain" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,205,0" Height="25" Width="55" />
<TextBox Name="DBGainValue" IsReadOnly="True" Text="{Binding ElementName=dbgainslider,Path=Value}" Width="40" Height="20" Margin="0,0,110,0" HorizontalAlignment="Center" VerticalAlignment="Center" />
<Slider Height="23" HorizontalAlignment="Center" Minimum="0.0" Maximum="59.5" TickFrequency="0.5" Margin="95,0,0,0" Name="dbgainslider" VerticalAlignment="Center" Width="160" />
</Grid>
</Grid>
</GroupBox>
CodecViewModel: Is a view model of CodecView.xaml
/// <summary>
/// Event for Refresh Button
/// </summary>
private ICommand mAddGroupBoxCommand;
public ICommand AddGroupBoxCommand
{
get
{
if (mAddGroupBoxCommand == null)
mAddGroupBoxCommand = new DelegateCommand(new Action(mAddGroupBoxCommandExecuted), new Func<bool>(mAddGroupBoxCommandCanExecute));
return mAddGroupBoxCommand;
}
set
{
mAddGroupBoxCommand = value;
}
}
public bool mAddGroupBoxCommandCanExecute()
{
return true;
}
public void mAddGroupBoxCommandExecuted()
{
//Here It should display the groupbox 4 times
}
ModelClass:
private string GroupBoxHeaderName;
public string GroupBoxHeader
{
get
{
return GroupBoxHeaderName;
}
set
{
GroupBoxHeaderName = value;
OnPropertyChanged("GroupBoxHeader");
}
}
Thus I want to add this Groupbox present in CodecWidgetView.xaml to my grid(NumberofCodecs) in CodecView.xaml on startup. And when I click the AddBoxButton it should dynamically generate the groupbox 4 times and display it :)
Now this is tricky, each Groupbox Header must display different names in every dynamically generated groupbox. Lets say on startup, 2 groupboxes are already displayed with Groupbox Header = "Location 1" and GroupBox Header = "Location 2". On AddgroupBox button click I want to have 4 groupboxes with Header as Groupbox Header = "Location 3" Groupbox Header = "Location 4" Groupbox Header = "Location 5" Groupbox Header = "Location 6".
Is it possible? :)
In the following code i am taking a itemscontrol in "CodecView.xaml" and for that itemscontrol ItemTemplate is your "CodecWidgetView.Xaml" and added description to that datatemplate. i have created another class CodecWidgetViewModel.cs which will be view model for "CodecWidgetView" view.
In the constructor of "CodecViewModel" i am creating instance for "CodecWidgetViewModel" and adding them to observable collection which is source of ItemsControl in the "CodecView"..
so at this point it will generate 2 CodecWidgetViews.. on button click i am adding 4 more instances so it will generate 4 CodecWidgetViews.. You can modify the code in the "mAddGroupBoxCommandExecuted" method as per your requirement..
on Button click
CodecView.XAML
<UserControl>
<UserControl.Resources>
<DataTemplate x:Key="CWDataTemplate">
<StackPanel>
<TextBlock Text="{Binding Description}"/>
<local:CodecWidgetView/>
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<Grid>
<Grid>
<ScrollViewer Name="GroupBoxScroll" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0" >
<Grid Name="NumberofCodecs" Style="{DynamicResource styleBackground}" >
<ItemsControl ItemTemplate="{StaticResource CWDataTemplate}" ItemsSource="{Binding CodecWidgets}"/>
</Grid>
</ScrollViewer>
</Grid>
<Button Content="Add Box" Name="AddBoxBtn" Command="{Binding AddGroupBoxCommand}" Click="AddBoxBtn_Click" HorizontalAlignment="Right" VerticalAlignment="Bottom" />
</Grid>
</UserControl>
CodecViewModel.cs
Create a property like this
public ObservableCollection<CodecWidgetViewModel> CodecWidgets { get; set; }
And add following code to your CodecViewModel constructor
CodecWidgets = new ObservableCollection<CodecWidgetViewModel>();
CodecWidgets.Add(new CodecWidgetViewModel { Description = "Location 1"});
CodecWidgets.Add(new CodecWidgetViewModel { Description = "Location 2" });
To Add widgets
public void mAddGroupBoxCommandExecuted()
{
CodecWidgets.Add(new CodecWidgetViewModel { Description = "Location 3" });
CodecWidgets.Add(new CodecWidgetViewModel { Description = "Location 4" });
CodecWidgets.Add(new CodecWidgetViewModel { Description = "Location 5" });
CodecWidgets.Add(new CodecWidgetViewModel { Description = "Location 6" });
}
Create following class
CodecWidgetViewModel.cs
public class CodecWidgetViewModel
{
private string _description;
public string Description {
get { return _description; }
set {
_description = value;
}
}
}
For some reason using Content="{Binding Time, StringFormat=t} is still giving me a long date. The backing field is a DateTime property initialised with DateTime.Now but no matter what string format I try it still shows the full date...
I would like only to see HH:mm tt
Any ideas?
XAML :
<Window x:Class="ArgosSystem.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:loc="clr-namespace:ArgosSystem"
xmlns:sys="clr-namespace:System;assembly=System"
Title="MainWindow" Height="800" Width="1280" Loaded="Window_Loaded">
<Window.Resources>
<DataTemplate DataType="{x:Type loc:Picknote}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" MinWidth="200" />
<ColumnDefinition Width="350" />
<ColumnDefinition Width="250" />
<ColumnDefinition Width="50" />
</Grid.ColumnDefinitions>
<Label Content="{Binding Time, StringFormat=t}" VerticalContentAlignment="Center" Foreground="IndianRed" FontSize="36" Grid.Column="0" />
<Label Content="{Binding Customer}" VerticalContentAlignment="Center" Foreground="IndianRed" FontSize="36" Grid.Column="1" />
<Label Content="{Binding PicknoteNo}" VerticalContentAlignment="Center" Foreground="IndianRed" FontSize="36" Grid.Column="2" />
<Label Content="{Binding Qty}" VerticalContentAlignment="Center" Foreground="IndianRed" FontSize="36" Grid.Column="3" />
</Grid>
</DataTemplate>
</Window.Resources>
<Grid Background="Black">
<DockPanel>
<ScrollViewer Name="lstPicknoteScroll" VerticalScrollBarVisibility="Auto">
<ItemsControl Name="lstPicknotes" ItemsSource="{Binding}" IsTabStop="False" Foreground="Cornsilk" />
</ScrollViewer>
</DockPanel>
</Grid>
</Window>
C# :
public partial class MainWindow : Window
{
ObservableCollection<Picknote> picknotes = new ObservableCollection<Picknote>();
public MainWindow()
{
InitializeComponent();
lstPicknotes.DataContext = picknotes;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
picknotes.Add(new Picknote
{
Time = DateTime.Now,
Customer = "REED FOR SPEED",
PicknoteNo = "PKN767677",
Qty = 100
});
picknotes.Add(new Picknote
{
Time = DateTime.Now.AddHours(-2),
Customer = "F1 AUTOMOTIVE",
PicknoteNo = "PKN767677",
Qty = 50
});
picknotes.Add(new Picknote
{
Time = DateTime.Now.AddHours(-1),
Customer = "FERGUSENS",
PicknoteNo = "PKN767677",
Qty = 10
});
}
}
StringFormat works on properties of type string. The Content property is of type Object so you need to specify the format using ContentStringFormat property of Label control.
<Label Content="{Binding Time}" ContentStringFormat="t" VerticalContentAlignment="Center" Foreground="IndianRed" FontSize="36" Grid.Column="0" />