Replace contents WPF grid control by grid in other XAML file - c#

I'm trying to replace the content of a WPF grid control by another WPF grid defined in a second XAML file in code (c#).
(simplified example)
Window1.xaml:
<Window x:Class="Demo1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="_Set Grid" Click="MenuItem_Click" />
</Menu>
<StatusBar DockPanel.Dock="Bottom">
<StatusBarItem Name="statusItem">Status</StatusBarItem>
</StatusBar>
<Grid Name="header" DockPanel.Dock="Top">
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Name="txtHi" Grid.Row="0" Grid.Column="0">Hi</TextBlock>
<TextBlock Name="txtName" Grid.Row="0" Grid.Column="1">X</TextBlock>
</Grid>
<Grid Name="gridContent">
</Grid>
</DockPanel>
Windows2.xaml contains the grid that replaces gridContent
<Window x:Class="Demo1.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window2" Height="300" Width="300">
<Grid Name="grid2">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label Grid.Column="1" Grid.Row="1">Hello !!!</Label>
</Grid>
The MenuItem_Click event in the code behind Windows1.xaml.cs contains:
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
Window2 win2 = new Window2();
gridContent = win2.grid2;
setStatus();
}
private void setStatus() {
statusItem.Content = "gridContent has " + gridContent.RowDefinitions.Count + " rows and " + gridContent.ColumnDefinitions.Count + " columns.";
}
Although the statusItem say the gridContent contains 2 rows and 2 columns after a click on the menu, the window is not changed and does not contain the text Hello!!!
Any ideas what I'm doing wrong?
If there are better solutions to "embed" a grid from a second xaml file, please let me know.
Thanks,
Robbie

Replacing the value of the gridContent variable cannot have an effect on the controls tree.
You must first disconnect the grid2 from its parent and then add it to the children of gridContent, like this:
win2.Content = null;
gridContent.Children.Add(win2.grid2);
This works (I tried), but it is not the recommended way to create a Window, extract its content then place it in another window. You should use a UserControl in place of Window2 and then you can put it directly inside gridContent.

Related

How can I select an item in a wpf combobox when it is a prefix of a previous item?

I'll start with my code example. It's a WPF Application.
MainWindow.xaml:
<Window x:Class="DemoComboBoxProblem.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:DemoComboBoxProblem"
mc:Ignorable="d"
Title="MainWindow" Height="60" Width="200">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ComboBox Name="CB0" Grid.Column="0" Width="60">
<ComboBoxItem>CRLF</ComboBoxItem>
<ComboBoxItem>CR</ComboBoxItem>
<ComboBoxItem>LF</ComboBoxItem>
<ComboBoxItem>LFCR</ComboBoxItem>
</ComboBox>
<ComboBox Name="CB1" Grid.Column="1" Width="60">
<ComboBoxItem>CRLF</ComboBoxItem>
<ComboBoxItem>AA</ComboBoxItem>
<ComboBoxItem>BB</ComboBoxItem>
<ComboBoxItem>LFCR</ComboBoxItem>
</ComboBox>
</Grid>
</Window>
MainWindow.xaml.cs:
using System.Windows;
namespace DemoComboBoxProblem
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
CB0.Text = "CR";
CB1.Text = "AA";
}
}
}
I want to programatically select the item "CR" in CB0 and the item "AA" in CB1.
When I run this, CB0 displays nothing and (I assume) no item is selected in it. CB1 correctly displays and has selected "AA". I think this has something to do with "CR" being a prefix of "CRLF". I can get it to work if I change the order of the items, but I'm wondering: what is the correct way to make it work with the items in the order given?
Thanks
Try this, add SelectedValuePath = "Content" to the combobox properties.
<ComboBox Name="CB0" Grid.Column="0" Width="60" SelectedValuePath="Content">
<ComboBoxItem>CRLF</ComboBoxItem>
<ComboBoxItem>CR</ComboBoxItem>
<ComboBoxItem>LF</ComboBoxItem>
<ComboBoxItem>LFCR</ComboBoxItem>
</ComboBox>
in the code use:
CB0.SelectedValue = "CR";
CB1.SelectedValue = "AA";

How to get WPF Window to autosize to content and no more

I have a dialog containing 2 TextBlocks, a Progress Bar and a cancel Button.
Here is the XAML:
<Window x:Class="WpfApplication4.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:WpfApplication4"
mc:Ignorable="d"
Title="MainWindow" Height="Auto" Width="200">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock x:Name="txtFirst" Grid.Row="0" Margin="5" TextWrapping="Wrap">This is a really really really really long string that wraps</TextBlock>
<TextBlock x:Name="txtSecond" Grid.Row="1" Margin="5" Text="A Shorter string" TextWrapping="Wrap" MaxWidth="200"/>
<ProgressBar x:Name="prgProgress" Grid.Row="2" Margin="5" Height="20" />
<Button x:Name="btnCancel" Grid.Row="3" Margin="5" Height="25" Width="50"/>
</Grid>
</Window>
I would like the Window not to have a fixed height but auto adjust its height based on the size of its children and no more, but can’t see a way to do this. At the moment when I don’t assign anything to the Window’s height, it seems to adopt a height that is much bigger that the content.
Not sure why, or where it gets height value from? If I set Windows Height = “Auto” I get the same thing. All the heights for the RowDefinitions are set to “Auto”, which I take to mean ‘set row height to be row child height’.
You need to use SizeToContent property, check the msdn link.
Example:
<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"
…
SizeToContent="WidthAndHeight">

How to setup textbox caret position to end of text?

I have Window with Frame and Page inside that frame.
That Page has one TextBox and i want to navigate that frame to another Page when someone started writing to that TextBox(similiar to google searching, when search result appears immediately on different view when you starts writing).
I am now using same DataContext for both Page objects, so they can both read the value of property searchedText, which i have binded to TextBox on each Page.
Page Search.xml:
<Page x:Class="Customer_UI.Search"
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"
Title="Search">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBox Name="searchBox" Grid.Column="0" Grid.Row="0" Margin="30" FontSize="28" Padding="10" TextAlignment="Center" VerticalAlignment="Center" BorderThickness="5" KeyUp="TextBox_KeyUp" Text="{Binding Path=SearchedCustomer}" >
</TextBox>
</Grid>
</Page>
Search code-behind:
namespace Customer_UI
{
public partial class Search : Page
{
private void TextBox_KeyUp(object sender, KeyEventArgs e)
{
SearchExpanded searchExpanded = new SearchExpanded();
searchExpanded.DataContext = this.DataContext;
(this.DataContext as MainWindow.MainWindowContext).MainWindow.MainFrame.Navigate(searchExpanded);
searchExpanded.FocusSearchBox();
}
}
}
Page SearchExpanded.xml:
<Page x:Class="Customer_UI.SearchExpanded"
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"
Title="SearchExpanded">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBox Name="searchBox" Grid.Column="0" Grid.Row="0" FontSize="18" Padding="10" TextAlignment="Center" VerticalAlignment="Center" BorderThickness="5" Text="{Binding Path=SearchedCustomer}" >
</TextBox>
</Grid>
</Page>
SearchExpanded code behind:
namespace Customer_UI
{
public partial class SearchExpanded : Page
{
public void FocusSearchBox()
{
MainWindow.MainWindowContext dc = DataContext as MainWindow.MainWindowContext;
// this has no output, the input from TextBox on Page that causes navigation to this page is probably still not reflected to dataContext.searchedCustomer property
Console.WriteLine(dc.SearchedCustomer);
// problem is that this time dc.SearchedCustomer has still lenght zero
searchBox.Focus();
}
}
}
Set the SelectionStart property to the length of the text.

AvalonDock document binding

I'm using AvalonDock (link) to create my application. I have a toolbar and a documentpane (VisualStudio like) and each new document contains a textbox. And now I'd like to add an Undo button to my toolbar which will undo changes on the textbox wich is placed on the selected document.It's completely same like it's in Visual Studio.
What I'd like to accomplish is answered here but with TabControl and Tabs.
MyCode:
<Window x:Class="_app.MainWindow"
xmlns:my="clr-namespace:_app"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ad="clr-namespace:AvalonDock;assembly=AvalonDock"
xmlns:osc="clr-namespace:OpenSourceControls;assembly=DockPanelSplitter"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="24"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="24"/>
</Grid.RowDefinitions>
<!--...Menu And Toolbars -->
<ToolBarPanel Grid.Row="1" Width="Auto" HorizontalAlignment="Stretch" >
<ToolBar>
<Button Command="Undo">Undo</Button>
</ToolBar>
</ToolBarPanel>
<ad:DockingManager x:Name="dockManager" Grid.Row="2">
<ad:ResizingPanel Orientation="Vertical">
<ad:ResizingPanel Orientation="Horizontal">
<ad:DockablePane ad:ResizingPanel.ResizeWidth="150">
<ad:DockableContent x:Name="inputContent" Title="Workspace">
<!-- some dockable windows -->
</ad:DockableContent>
</ad:DockablePane>
<!-- here are added the new Documents-->
<ad:DocumentPane Name="mainDocPane" ItemsSource="{Binding ..Don't know..}">
<ad:DocumentPane.ItemContainerStyle>
<Style TargetType="ad:DocumentContent">
<Setter Property="Content" Value="{Binding Content}"/>
</Style>
</ad:DocumentPane.ItemContainerStyle>
</ad:DocumentPane>
</ad:ResizingPanel>
</ad:ResizingPanel>
</ad:DockingManager>
</Grid>
I create new document windows like this:
private void NewDocument_Click(object sender, RoutedEventArgs e)
{
string title = "Document" + (dockManager.Documents.Count+1).ToString();
var doc = new Document() { Title = title };
doc.Show(dockManager);
doc.Activate();
}
And the document class looks like this:
public partial class Document : AvalonDock.DocumentContent
{
public Document()
{
InitializeComponent();
}
}
XAML:
<ad:DocumentContent x:Class="_ap.Document"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:osc="clr-namespace:OpenSourceControls;assembly=DockPanelSplitter"
xmlns:ad="clr-namespace:AvalonDock;assembly=AvalonDock">
<DockPanel>
<TextBox Name="input" AcceptsReturn="True" />
</DockPanel>
So I'd like to apply the same mechanism from the link above on this code.
Thanks for any help.
See the ApplicaionCommands.Undo
Once you tie your Undo button to the in place command which comes with the .NET FW, when the TextBox has focus the undo will take place without you having to do anything.

WPF Moving Element problem

I am probably over-doing a very simple problem, but this is what I have a the moment:
I have several buttons and a listbox of items in which the user can select and interact with. My application also moves those elements in accordance to the application width/height, such as follows:
listBox1.Margin = new Thickness(this.ActualWidth * 0.84, this.ActualHeight * 0.3, 0, 0);
I am able to select the items within the listbox and click on buttons appropriately while in windowed mode, but as I begin to stretch the application larger, I try to click on the items, and I cannot do so.. is this because I also need to update their hit-detection rectangles as well? Or perhaps am I moving the items incorrectly? I am at a loss.. any information would be very helpful at this point...thanks!
Not sure why you can't click the items anymore after resizing. That can have a lot of reasons. Obviously you want to have proportional margins around the ListBox. You would normally do that with a Grid:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.83*"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="0.3*"/>
<RowDefinition/>
</Grid.RowDefinitions>
<ListBox x:Name="listBox1" Grid.Column="1" Grid.Row="1"/>
</Grid>
I write this XAML:
<Window x:Class="StackOverflow_MovingProblem.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">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ListBox Name="listbox1" ItemsSource="{Binding Path=list}" />
<StackPanel Grid.Row="1" Orientation="Horizontal">
<Button Content="button1" />
<Button Content="button2" />
<Button Content="button3" />
</StackPanel>
</Grid>
</Window>
with this code-behind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
SizeChanged += new SizeChangedEventHandler(MainWindow_SizeChanged);
list = new ObservableCollection<string>();
list.Add("item1");
list.Add("item2");
list.Add("item3");
}
public ObservableCollection<string> list { get; set; }
void MainWindow_SizeChanged(object sender, SizeChangedEventArgs e)
{
listbox1.Margin = new Thickness(this.ActualWidth * 0.84,
this.ActualHeight * 0.3, 0, 0);
}
}
but I'm not able to reproduce your problem. Check my code if there is something different with your code and tell me what, so I can give you some advices. Thank you

Categories