I'm working on a game where I am using a UI framework which works with XAML and MVVM. I have managed to get my framework hooked up and I am able to switch between views. Right now I am using data-templates along with the ContentControl to switch views, I am also using a state-like pattern to switch and I was wondering if this is a good approach to use? I am having a small problem with my views, the way I have things set up currenly I have my MainWindow.xaml which contains a data-template to my other xaml files. The problem is the views just get added to the MainWindow.xaml and I'm wondering if there is a way to hide the previous view/content so it looks as if I'm switching between windows/views rather than just adding to them. Here is a screenshot to illustrate what I currently have.Image of project. My xaml files are very simple and just contain a button for now, here are my xaml files:
`
MainWindow.xaml
<Grid
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"
xmlns:local="clr-namespace:PsalmsOfEia"
xmlns:viewmodels="clr-namespace:PsalmsOfEia.UI.Menus.ViewModels"
xmlns:views="clr-namespace:PsalmsOfEia.UI.Menus.Views">
<Grid.DataContext>
<viewmodels:MainViewModel />
</Grid.DataContext>
<Grid.Resources>
<DataTemplate DataType="{x:Type viewmodels:LoginViewModel}">
<views:LoginView/>
</DataTemplate>
</Grid.Resources>
<DockPanel LastChildFill="True">
<StackPanel>
<ContentControl Content="{Binding SelectedViewModel}"/>
<Button Content="Login" Command="{Binding ChangeCommand}"/>
</DockPanel>
</Grid>
LoginView.xaml
<UserControl x:Class="PsalmsOfEia.UI.Menus.Views.LoginView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:PsalmsOfEia"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
xmlns:viewmodels="clr-namespace:PsalmsOfEia.UI.Menus.ViewModels"
xmlns:views="clr-namespace:PsalmsOfEia.UI.Menus.Views">
<UserControl.DataContext>
<viewmodels:LoginViewModel />
</UserControl.DataContext>
<UserControl.Resources>
<DataTemplate DataType="{x:Type viewmodels:CreateCharacterViewModel}">
<views:CreateCharacterView/>
</DataTemplate>
</UserControl.Resources>
<StackPanel>
<ContentControl Content="{Binding SelectedViewModel}"/>
<Button Content="Click Here" Command="{Binding LoginCommand}"/>
</StackPanel>
</UserControl>
`
Could anyone tell me if there is a better way of switching views as well as how to hide the content of the previous views (since at the moment everything is being added to the main window).
Thanks
-Joshmond
Not really sure what you're looking for but I use a TabControl
<TabControl>
<TabItem Header="Tab1">
<local:UserControl1/>
</TabItem>
<TabItem Header="Tab2">
<local:UserControl2/>
</TabItem>
<TabItem Header="Tab3">
<local:UserControl3/>
</TabItem>
</TabControl>
I try to minimise the amount of XAML in one file, so I create a UserControl and add them into the main view.
Im using stackpanel and usercontrol.
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel x:Name="myStackpanel1" Grid.Row="0" />
<StackPanel x:Name="myStackpanel2" Grid.Row="1" />
<Button x:Name="myButton" Width="200" Height="30" Grid.Row="2" Click="myButton_Click" Content="Click Me SP1" />
<Button x:Name="myButton2" Width="200" Height="30" Grid.Row="3" Click="myButton2_Click" Content="Click Me2 SP2" />
</Grid>
Code
private int i,j = 0;
public MainWindow()
{
InitializeComponent();
}
private void myButton_Click(object sender, RoutedEventArgs e)
{
i++;
if (i % 2 == 0)
{
myStackpanel1.Children.Clear();
myStackpanel1.Children.Add(new UserControl1());
}
else
{
myStackpanel1.Children.Clear();
myStackpanel1.Children.Add(new UserControl2());
}
}
private void myButton2_Click(object sender, RoutedEventArgs e)
{
j++;
if (j % 2 == 0)
{
myStackpanel2.Children.Clear();
myStackpanel2.Children.Add(new UserControl2());
}
else
{
myStackpanel2.Children.Clear();
myStackpanel2.Children.Add(new UserControl1());
}
}
Related
Learning C#, specifically WPF, and the MVVM framework. I'm creating a basic project that presents a MainWindow with a contentcontrol binding. Straightforward.
I have 2 views, each with a textbox. I have 2 buttons on the MainWindow, each allow me to toggle between views. However, when I enter data in a textbox, switch views, and come back, the data is gone. How can I persist that data to be consumed later?
Relevant code:
MainWindow.xaml
<Window x:Class="TestDataRetention.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:TestDataRetention"
xmlns:views="clr-namespace:TestDataRetention.Views"
xmlns:viewmodels="clr-namespace:TestDataRetention.ViewModels"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<DataTemplate DataType="{x:Type viewmodels:View1ViewModel}">
<views:View1View DataContext="{Binding}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewmodels:View2ViewModel}">
<views:View2View DataContext="{Binding}"/>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="60"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Grid.Row="1" HorizontalAlignment="Right">
<Button x:Name="View1Button" Margin="10" Width="80" Content="View1" Click="View1Button_Click"/>
<Button x:Name="View2Button" Margin="10" Width="80" Content="View2" Click="View2Button_Click"/>
</StackPanel>
<ContentControl x:Name="Content" Grid.Row="0" Content="{Binding}"/>
</Grid>
</Window>
MainWindow.xaml.cs
using System.Windows;
using TestDataRetention.ViewModels;
namespace TestDataRetention
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void View1Button_Click(object sender, RoutedEventArgs e)
{
DataContext = new View1ViewModel();
}
private void View2Button_Click(object sender, RoutedEventArgs e)
{
DataContext = new View2ViewModel();
}
}
}
View1View.xaml
<UserControl x:Class="TestDataRetention.Views.View1View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:TestDataRetention.Views"
xmlns:vm="clr-namespace:TestDataRetention.ViewModels"
mc:Ignorable="d"
FontSize="24"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.DataContext>
<vm:View1ViewModel/>
</UserControl.DataContext>
<Grid Background="AliceBlue">
<StackPanel>
<Label HorizontalAlignment="Center" Content="Enter View1 Stuff"/>
<TextBox x:Name="View1TextBox" Width="400" Height="50" Text="{Binding View1Words}" />
</StackPanel>
</Grid>
</UserControl>
View1View.xaml.cs
using System.Windows.Controls;
using TestDataRetention.ViewModels;
namespace TestDataRetention.Views
{
public partial class View1View : UserControl
{
public View1View()
{
InitializeComponent();
this.DataContext = new View1ViewModel();
}
}
}
View2 is obviously the same as View1 but with corresponding variables.
While there might also be a way to just have wpf cache it for you, you can just as easily save it properly and then have the input available at will.
Look here for two methods on how to:
How to save user inputed value in TextBox? (WPF, XAML)
At quick glance, you create new ViewModel each time your button is clicked, this will always create new ViewModel for your DataContext not using the original one.
Also this snippet from your code will create new ViewModel for your Control's DataContext regardless of the one the parent control has:
<UserControl.DataContext>
<vm:View1ViewModel/>
</UserControl.DataContext>
And I am not sure how you use your DataTemplate here:
<DataTemplate DataType="{x:Type viewmodels:View1ViewModel}">
<views:View1View DataContext="{Binding}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewmodels:View2ViewModel}">
<views:View2View DataContext="{Binding}"/>
</DataTemplate>
But generally, as a guidance for you to model your MVVM project, always keep in mind that XAML code is translated to C# while compiling. So when writing something like <vm:View1ViewModel/> you actually do new View1ViewModel().
So for you to use the DataContext your control inherited from its parent, you just use <UserControl DataContext="{binding}" for your UserControl.
And for your button click, you have to keep a pointer for your previously created ViewModel and assign it to the DataContext when needed, I suggest you to create these ViewModels only when needed to minimize memory consumption in large applications, like:
private View1ViewModel m_View1VM = null;
private void View1Button_Click(object sender, RoutedEventArgs e)
{
if (m_View1VM is null)
m_View1VM = new View1ViewModel();
this.DataContext = m_View1VM;
}
So, I'm fairly new to C#/XAML and have been trying to teach myself MVVM by reworking an old project. I ran into a problem where a user-control is supposed to be added to a uniformgrid. The user-control shows up fine if I implement it by itself, but if I add it to a ObservableCollection and then try to bind that to a uniformgrid, the path to the user-control gets displayed rather than the actual UI element. Unfortunately I'm new enough to C# and MVVM that I can't identify what specifically is the problem, which makes it hard to search online for.
<UserControl x:Class="CMS.Views.MonthView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CMS.Views"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<ItemsControl ItemsSource="{Binding Dates}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid IsItemsHost="True" Columns="7"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
</UserControl>
MonthView.cs
namespace CMS.Views
{
public partial class MonthView : UserControl
{
public MonthView()
{
InitializeComponent();
MonthViewModel monthViewModelObject = MonthViewModel.GetMonthViewModel();
this.DataContext = monthViewModelObject;
}
}
}
MonthViewModel
namespace CMS.ViewModels
{
class MonthViewModel
{
private readonly ObservableCollection<DayViewModel> _dates = new ObservableCollection<DayViewModel>();
public IReadOnlyCollection<DayViewModel> Dates
{
get { return _dates; }
}
public static MonthViewModel GetMonthViewModel()
{
var month = new MonthViewModel();
month.testdaymodel();
return month;
}
public void testdaymodel()
{
DayViewModel DVM = DayViewModel.GetDayViewModel();
DVM.LoadDate(DateTime.Now);
_dates.Add(DVM);
}
}
}
DayView's XAML which has the DataTemplate
<UserControl x:Class="CMS.Views.DayView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CMS.Views"
mc:Ignorable = "d"
MinWidth="100" MinHeight="100" BorderBrush="LightSlateGray" BorderThickness="0.5,0.5,1.5,1.5">
<UserControl.Resources>
<ResourceDictionary>
</ResourceDictionary>
</UserControl.Resources>
<DataTemplate x:Name ="DayBox">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="21"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border x:Name="DayLabelRowBorder" CornerRadius="2" Grid.Row="0" BorderBrush="{x:Null}" Background="{DynamicResource BlueGradientBrush}">
<Label x:Name="DayLabel" Content="{Binding Path = Info.Day, Mode = OneWay}" FontWeight="Bold" FontFamily="Arial"/>
</Border>
<!--This will be bound to the event schedule for a given day-->
<StackPanel Grid.Row="1" x:Name="DayAppointmentsStack" HorizontalAlignment="Stretch" Background="White" VerticalAlignment="Stretch">
</StackPanel>
</Grid>
</DataTemplate>
</UserControl>
EDIT: The same rule applies whether you're using a simple control like a Label or your own control like DayView.
You need to set the ItemsControl.ItemTemplate that will be bound to each item from your IReadOnlyCollection<DayViewModel>.
Then, make a DataTemplate of your liking. Like this:
<ItemsControl ItemsSource="{Binding Dates}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid IsItemsHost="True" Columns="7"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- This control is automatically bound to each DayViewModel instance -->
<local:DayView />
<!--
<Label Content="{Binding PropertyToDisplay}" ></Label>
-->
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
You didn't show the DayViewModel class, so you can just change the PropertyToDisplay to the actual property you want your view to display.
EDIT: Making DayView the ItemsControl.Template will automatically bind it to the type of the items in the ItemSource.
That means you can treat DayView like a UserControl with DayViewModel as its DataContext without explicitly setting it.
I am assuming that the actual View of your DayView is the Grid inside the DataTemplate, so I just modified the code as follows:
DayView.xaml
<UserControl x:Class="CMS.Views.DayView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CMS.Views"
mc:Ignorable = "d"
MinWidth="100" MinHeight="100" BorderBrush="LightSlateGray" BorderThickness="0.5,0.5,1.5,1.5">
<UserControl.Resources>
<ResourceDictionary>
</ResourceDictionary>
</UserControl.Resources>
<!-- <DataTemplate x:Name ="DayBox"> -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="21"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border x:Name="DayLabelRowBorder" CornerRadius="2" Grid.Row="0" BorderBrush="{x:Null}" Background="{DynamicResource BlueGradientBrush}">
<Label x:Name="DayLabel" Content="{Binding Path = Info.Day, Mode = OneWay}" FontWeight="Bold" FontFamily="Arial"/>
</Border>
<!--This will be bound to the event schedule for a given day-->
<StackPanel Grid.Row="1" x:Name="DayAppointmentsStack" HorizontalAlignment="Stretch" Background="White" VerticalAlignment="Stretch">
</StackPanel>
</Grid>
<!-- </DataTemplate> -->
</UserControl>
First of all it's my first day using Xaml so this question might be dummy for you, but i totally got lost.
Overview
My technique is that i have MainWindow.xaml and it's split into three areas (using grid columns) the columns width being set automatically.
Based on some actions in the right column, the middle column with show a page let's say Page.xaml that exists in different namespace.
What i'm seeking for
The problem is i need to set the width and height for this page to be equal the middle column width and height as it will fit this area.
Notes
I have very small experience with xaml and binding techniques.
MainWindow.Xaml
<Window
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"
WindowState="Maximized"
ResizeMode="NoResize"
WindowStartupLocation="CenterScreen"
Title="MainWindow" d:DesignWidth="1366" d:DesignHeight="768">
<Grid x:Name="MainGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1.2*" x:Name="LeftColoumn" />
<ColumnDefinition Width="3*" x:Name="CenterColoumn" />
<ColumnDefinition Width=".8*" x:Name="RightColoumn" />
</Grid.ColumnDefinitions>
<ScrollViewer Grid.Column="2">
<StackPanel Orientation="Vertical" x:Name="RightStackPanel" Background="LightGray" >
<Border BorderBrush="{x:Null}" Height="50" >
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" TextWrapping="Wrap" FontWeight="SemiBold" FontStyle="Normal" Margin="3" FontSize="20" >Others</TextBlock>
</Border>
<Expander x:Name="Expander1" Header="Others" Margin="0,0,10,0">
<Button Margin="0,0,0,0" Width="{Binding ActualWidth, ElementName=RightStackPanel}" Background="White" Content="Add" Height="50" Click="Button_Click" ></Button>
</Expander>
</StackPanel>
</ScrollViewer>
<Frame Grid.Column="0" x:Name="LeftFrame" Background="LightGray" ></Frame>
<Frame Grid.Column="1" x:Name="CenterFrame" Background="DarkGray" ></Frame>
</Grid></Window>
Other Xaml file
<Page
x:Name="Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
Title="Any" d:DesignWidth="1364" d:DesignHeight="868"
>
<Grid>
<Frame Background="DarkGray" />
</Grid></Page>
MainWindow.xaml.cs
private void Button_Click(object sender, RoutedEventArgs e)
{
Frame middleFrame=CenterColumn;
Otherxaml other=new Otherxaml();
middleFrame.Source = new Uri("OtherxamlPage.xaml", UriKind.RelativeOrAbsolute);
}
Pertinent to your code snippet, you may place the OtherxamlPage.xaml inside the central frame and set the properties of that frame like shown below:
<Frame Grid.Column="1" x:Name="CenterFrame" VerticalAlignment="Stretch" VerticalContentAlignment="Center" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" Source="OtherxamlPage.xaml" Background="DarkGray" />
You can set the Source="OtherxamlPage.xaml" dynamically in event handler, e.g. Button.Click as per your example.
Alternatively, consider the creation of WPF UserControl (re: https://msdn.microsoft.com/en-us/library/cc294992.aspx) instead of that other XAML Window (or Page) and place it directly into the grid cell. In both cases set the content "Stretch" property in order to adjust its size automatically, thus you won't need to specify it in the code.
Hope this may help.
I have a user control (UserInfo.xaml) and I want to load this my main tab control.
My goal is to seprate the user control from the tab control.
I cant seem to do this in WPF
My user control looks like this.
<UserControl x:Class="AuthWiz.UserInfo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="750" d:DesignWidth="1000">
<Grid>
<Label Content="Request authorization for New User" HorizontalAlignment="Left" Margin="30,30,0,0" VerticalAlignment="Top" FontSize="20" FontWeight="Bold"/>
</Grid>
I want to load the usercontrol "userinfo" in this Tabcontrol like this.
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:AuthWiz;assembly=AuthWiz" x:Class="AuthWiz.TabControl"
mc:Ignorable="d"
d:DesignHeight="750" d:DesignWidth="1000">
<Grid>
<TabControl HorizontalAlignment="Left" Height="677" Margin="10,63,0,0" VerticalAlignment="Top" Width="980" TabStripPlacement="Top">
<TabItem Header="New User">
<Grid Background="#FFE5E5E5">
<local:UserInfo /> #this does not work.
</Grid>
</TabItem>
</TabControl>
</Grid>
I recieve the following error
The tag 'UserInfo' does not exist in XML namespace 'clr-namespace:AuthWiz;assembly=AuthWiz'.
TabItem can only have one child element, therefore the following is incorrect:
<TabItem Header="New User">
<Grid Background="#FFE5E5E5"/>
<local:UserInfo /> #this does not work.
</TabItem>
Because your TabItem has a Grid, and your UserControl. To solve this problem, simply place your UserControl inside your Grid.
<TabItem Header="New User">
<Grid Background="#FFE5E5E5">
<local:UserInfo />
</Grid>
</TabItem>
I have written a toy WPF application with a Button and an ItemsControl. Each time you click the Button, the string "AnotherWord" gets added to the ItemsControl. Now, the ItemsControl is displayed as horizontally oriented StackPanel with a fixed width (500 pixels). This means that when you click the button a certain number of times (actually six times), the newly added string gets clipped, like this:
"AnotherWord AnotherWord AnotherWord AnotherWord AnotherWord AnotherWo"
This happens when the FontSize is 13; if you lower it to 12.7 then there's room for the sixth occurence of "AnotherWord". My question is: Is there a way to make this adjustment at runtime so that you avoid the overflow?
EDIT:
In the context of the question, the fixed width of the StackPanel is obligatory - we cannot use more than the 500 pixels we have. Another requirement that the font must never become bigger than 13.
Here is all the code I wrote:
<!-- MainWindow.xaml -->
<Window x:Class="FontSize.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Window.Resources>
<DataTemplate x:Key="labelTemplate">
<Label FontSize="13" Content="AnotherWord"></Label>
</DataTemplate>
<ItemsPanelTemplate x:Key="panelTemplate">
<StackPanel Orientation="Horizontal" Width="500" Height="50" />
</ItemsPanelTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ItemsControl Grid.Row="0" ItemsSource="{Binding Path=MyStrings}" ItemTemplate="{StaticResource labelTemplate}"
ItemsPanel="{StaticResource panelTemplate}" />
<Button Grid.Row="1" Click="Button_Click"></Button>
</Grid>
</Window>
// MainWindow.xaml.cs
using System.Collections.ObjectModel;
using System.Windows;
namespace FontSize
{
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
MyStrings = new ObservableCollection<string>();
}
public ObservableCollection<string> MyStrings
{
get { return (ObservableCollection<string>) GetValue(MyStringsProperty); }
set { SetValue(MyStringsProperty, value); }
}
private static readonly DependencyProperty MyStringsProperty =
DependencyProperty.Register("MyStrings", typeof (ObservableCollection<string>), typeof (Window));
private void Button_Click(object sender, RoutedEventArgs e)
{
MyStrings.Add("AnotherWord");
}
}
}
Put your ItemsControl in a Viewbox and play with the following properties:
MaxWidth
MaxHeight
Stretch
StretchDirection
Edit
And remove the Width & Height property of your StackPanel.
Edit 2
Try something like that:
<!-- MainWindow.xaml -->
<Window x:Class="FontSize.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Window.Resources>
<DataTemplate x:Key="labelTemplate">
<Label FontSize="13" Content="AnotherWord"></Label>
</DataTemplate>
<ItemsPanelTemplate x:Key="panelTemplate">
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Viewbox Grid.Row="0" MaxWidth="500" Stretch="Uniform">
<ItemsControl
ItemsSource="{Binding Path=MyStrings}"
ItemTemplate="{StaticResource labelTemplate}"
ItemsPanel="{StaticResource panelTemplate}" />
</Viewbox>
<Button Grid.Row="1" Click="Button_Click"></Button>
</Grid>
</Window>
Edit 3
Change the horizontal alignment of the Viewbox so it isn't stretched to fill the grid. I've put "Center", replace by whatever you want.
...
<Viewbox
HorizontalAlignment="Center"
StretchDirection="DownOnly"
Grid.Row="0"
MaxWidth="500"
Stretch="Uniform">
...