Dynamically reducing FontSize to avoid overflow - c#

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">
...

Related

Bound User-Controls in an ObservableCollection aren't showing up in uniformgrid

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>

Automatically set window width and height to ItemsControl Item

I have a base window which acts as a generalised container for UserControls. It works as expected, except the width and the height do not seem to be determined by the size of the child item (which with width and height set to auto, I would expect). The xaml for the base window is as follows:
<local:BaseView x:Class="Program.UI.Views.BaseWindowView"
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:Program.UI.Views"
xmlns:converters="clr-namespace:Program.UI.Converters"
xmlns:presenter="clr-namespace:Program.Presenter"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
mc:Ignorable="d"
ResizeMode="NoResize" WindowStyle="None"
d:DesignHeight="300" d:DesignWidth="300" AllowsTransparency="True">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
<presenter:EventToCommand Command="{Binding Mode=OneWay, Path=CloseWindow}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<local:BaseView.Resources>
<ResourceDictionary>
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<converters:SystemEventToForegroundColor x:Key="SystemEventToForegroundColor" />
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Program;component/UI/Templates/Generic.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</local:BaseView.Resources>
<local:BaseView.Foreground>
<SolidColorBrush Color="Black" Opacity="100"/>
</local:BaseView.Foreground>
<local:BaseView.Background>
<SolidColorBrush Color="White" Opacity="0"/>
</local:BaseView.Background>
<Border BorderBrush="#FF838383" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" BorderThickness="1" Height="auto" Width="auto" Margin="0,0,5,5">
<Canvas Background="#E8F6F6" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Height="auto" Width="auto">
<Canvas.Effect>
<DropShadowEffect RenderingBias="Quality" Opacity="0.3" ShadowDepth="3" BlurRadius="4"/>
</Canvas.Effect>
<DockPanel VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
Margin="0,0,0,0" x:Name="ReferenceInfo" Canvas.Left="0" Canvas.Top="0"
Width="{Binding ActualWidth, ElementName=InfoCanvas}"
Height="{Binding ActualHeight, ElementName=InfoCanvas}"
d:DesignWidth="294"
d:DesignHeight="294">
<Grid Width="auto" Height="auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Width="auto" HorizontalAlignment="Stretch" Height="30" VerticalAlignment="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<Border Grid.Column="0" BorderBrush="#FF838383" BorderThickness="0,0,0,1" Height="30" VerticalAlignment="Top">
<Label Style="{StaticResource WindowHeaderControlTitle}" MouseDown="Label_MouseDown"/>
</Border>
<Border Grid.Column="1" BorderBrush="#FF838383" BorderThickness="1,0,0,1">
<Label Style="{StaticResource WindowHeaderControlCloseLabel}" MouseEnter="Label_MouseEnter" MouseLeave="Label_MouseLeave" MouseLeftButtonUp="Label_MouseLeftButtonUp" MouseLeftButtonDown="Label_MouseLeftButtonDown" FontSize="14" FontFamily="Segoe UI Black" FontStretch="UltraExpanded" Content="X"/>
</Border>
</Grid>
<ItemsControl Grid.Row="1" Height="auto" Width="auto" ItemsSource="{Binding ChildView}"/>
</Grid>
</DockPanel>
</Canvas>
</Border>
The view is generated on the click event of an Excel ribbon button, the code-behind for which is:
var childView = new DatapointDefinitionsView();
childView.DataContext = new DatapointDefinitionsViewModel();
ApplicationData.Presenter.ShowView<BaseWindowView>(
new BaseWindowViewModel(childView, ApplicationData.Presenter), true);
The ShowView code is:
private BaseWindowView _windowView;
public void ShowView<T>(BaseWindowViewModel viewModel, bool asModal) where T : BaseWindowView, new()
{
_windowView = new T
{
DataContext = viewModel,
ShowInTaskbar = false,
Title = viewModel.Caption,
};
//Width = viewModel.ChildView[0].Width,
//Height = viewModel.ChildView[0].Height
if (asModal)
{
_windowView.ShowDialog();
_windowView = null;
}
else
{
_windowView.Show();
}
}
Setting the width and height explicitly to the child height will set the width to the specified width, but has no effect on the height. Even if it did, however, this is not a satisfactory solution as it means the values are fixed and will not update if the usercontrol dimensions change.
Is there another way to achieve what I want?
So I was able to resolve this in the end, with all the desired functionality, as follows:
I bound the canvas height (in xaml) to the height of the DockPanel
Height="{Binding ElementName=ReferenceInfo, Path=ActualHeight}"
but the width to the ItemsControl element
Width="{Binding ElementName=ChildUserControl, Path=ActualWidth}"
I removed Height and Width from the DockPanel and re-enabled SizeToContent="WidthAndHeight" window attribute as per #lokusking earlier suggestion.
In order to enable CanResizeWithGrip functionality (and have the content of the child usercontrol dynamically resize accordingly) I hooked into the window SizeChanged event and added the following code:
private void BaseView_SizeChanged(object sender, SizeChangedEventArgs e)
{
var window = sender as Window;
if (ChildUserControl.HasItems)
{
var chlidControl = ChildUserControl.Items[0] as UserControl;
var context = (BaseWindowViewModel)window.DataContext;
// Ignore the first 3 resize events - these occur on view generation
if (!context.InitialResizeComplete)
if (context.ResizeOperations < 3)
{
context.ResizeOperations++;
return;
}
context.InitialResizeComplete = true;
// Subtract all fixed size elements from window dimensions
chlidControl.Width = window.ActualWidth - (OuterBorder.BorderThickness.Left + OuterBorder.BorderThickness.Right + OuterBorder.Margin.Right + OuterBorder.Margin.Left);
chlidControl.Height = window.ActualHeight - (OuterBorder.BorderThickness.Top + OuterBorder.BorderThickness.Bottom + OuterBorder.Margin.Top + OuterBorder.Margin.Bottom + TaskBarGrid.Height);
}
}
I've yet to determine what drives the initial 3 resize operations. My first guess was initialisation, then x, then y - but on reflection it could possibly be 1 for the baseview, 1 for the basewindow and 1 for the usercontrol. If that's the case then attached usercontrols that themselves have multiple views could prove problematic using this approach, but I've yet to test.
Hope somebody can find this useful, and thanks to those who offered help.

How to embed WPF Window into another Window and adjust its size via XAML or code

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.

MinWidth, MaxWidth, MinHeight, MaxHeight don't have effect for <UserControl>

I'm learning to create WPF application with Caliburn Micro framework.
Following the tutorial on the homepage: Basic Configuration, I removed the default generated <Window> xaml, instead, I have <UserControl> xaml and bootstrap it via my AppBoostrapper.
Here is the MainView.xaml:
<UserControl x:Class="SmartRenamer.Views.MainView"
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="300" d:DesignWidth="300"
MinHeight="300"
MinWidth="300"
MaxHeight="500"
MaxWidth="1000">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Menu IsMainMenu="True" Grid.Row="0">
<MenuItem Header="_File">
<MenuItem Header="_Open Folder..." x:Name="OpenFolder"></MenuItem>
</MenuItem>
<MenuItem Header="_About" />
</Menu>
<ScrollViewer HorizontalScrollBarVisibility="Visible" Grid.Row="1" MaxHeight="500" MaxWidth="1000">
<StackPanel>
<DataGrid x:Name="FilesList">
</DataGrid>
</StackPanel>
</ScrollViewer>
</Grid>
</UserControl>
The problem is I want to set the MinWidth, MaxWidth, MinHeight, MaxHeight for my application, but it seems that those configuration in the MainWindow.xaml isn't working.
Here is the two screenshots, where the window is still can be re-sized out of the defined range:
What am I wrong here?
The width and height properties of an UserControl is set by the container that holds that control. I.e. the DesignWidth and DesignHeigth that are used in the design-time are set in the UserControl but in runtime it uses the values set by the container.
I am not experienced in Caliburn Micro but it seems like you can define the design properties in the bootstrapper:
var settings = new Dictionary<string, object>
{
{ "Height" , 300},
{ "Width" , 300},
};
DisplayRootViewFor<ViewModel>(settings);

New item activated in Conductor does not show it

I'm activating new item in conductor using Caliburn.Micro.Contrib's ConductResult. Conductor is of type Conductor<IScreen>.Collection.OneActive, and there is already one item showing and working correctly.
The new item however is not shown after it was activated. I already checked and the conductor's ActiveItem is set to that new item, new item is activated as well. View's IsVisible of new item is also set to true, so I don't understand why it is not visible.
XAML of the conductor's view is pretty simple:
<UserControl x:Class="..."
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:cal="http://www.caliburnproject.org"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding Path=ActiveItem, Converter={StaticResource objectTypeConverter}}" Margin="5" />
<ItemsControl Grid.Row="1" ItemsSource="{Binding Items}" BorderBrush="Aqua" BorderThickness="10 ">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Converter={StaticResource objectTypeConverter},ConverterParameter=something}" Margin="5" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ContentControl Grid.Row="2" x:Name="ActiveItem" />
</Grid>
</UserControl>
(TextBlock and ItemsControl are there for debugging purposes; they prove that new item is conducted within conductor (i.e. Items collection contains it) and new item is set as ActiveItem)
In my case, I was using IoC.Get<IShell> to access the parent viewmodel.
The default bootstrapper says container.PerRequest<IShell, ShellViewModel>();
That’s why I was getting another instance of my ShellViewModel class, activated the item just fine, but no UI was updating.
One way to fix is replace container.PerRequest with container.Singleton.
Another is change IoC.Get<IShell>() into ( (IShell)Parent )

Categories