I already know how to compose User Control and access inner control properties with Dependency Properties in XAML User Control.
My question is, how to access a control itself inside of User Control.
For example,
User Control: TbCanvas.xaml
<UserControl
x:Class="Sample.Control.TbCanvas"
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"
d:DesignHeight="300"
d:DesignWidth="400"
x:Name="root">
<Grid>
<Image x:Name="imageMain" />
</Grid>
</UserControl>
I'd like to use it in some Page that has above User Control as below.
SomePage.xaml.cs
this.tbCanvas.imageMain.Source = "some_path";
Of course, the Source can be given as Dependency Property with Binding, but I sometimes need to access inner controls because every property of controls are not entirely bindable.
Check out these links
C# usercontrol how to access all child controls
how to get child user control by id from a parent panel user control?
http://www.daniweb.com/software-development/csharp/threads/141469/how-to-access-child-control-of-a-user-control
Related
If a ParentUserControl contains a TextBlock. The ParentUserControlalso contains ChildUserControl that has a TextBox. I want to set the TextBlock of ParentUserControl value from ChildTextBox. how can i ?
In other words somehow accessing the ParentUserControl and it's TextBlock element and then modifying it's value from ChildUserControl !
Update
i have a xaml window that contains a ParentUserControl that has a TextBlock. Now i am loading or adding another ChildUserControl into it on runtime. This newly added ChildUserControl contains a ChildTextBox. Now i want that when i input some value into this ChildTexBox the ParentUserControl's TextBlock should get that value and update itself.
Assuming we are not following any MVVM and a simple approach for this problem is,
Create a ChildUserControl with a textbox inside it as below,
<UserControl x:Class="SO52840402.ChildUserControl"
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:SO52607887"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<TextBox x:Name="ChildTextBox" />
</Grid> </UserControl>
Create a ParentUserControl which contains a TextBlock and ChildUserControl instance as shown below,
<UserControl x:Class="SO52840402.ParentUserControl"
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:SO52607887"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock x:Name="ParentTextBlock" Text="Hallo World!"/>
<local:ChildUserControl x:Name="ChildUserControl" Grid.Row="1" />
</Grid> </UserControl>
Now create a TextChanged event for the TextBox which is under ChildUserControl from code behind of ParentUserControl constructor after "InitializeComponent" as shown below,
public ParentUserControl()
{
InitializeComponent();
ChildUserControl.ChildTextBox.TextChanged += OnChildTextBox_TextChanged;
}
private void OnChildTextBox_TextChanged(object sender, EventArgs e)
{
ParentTextBlock.Text = (sender as TextBox).Text;
}
Note:- This is a not a recommended approach. For best approach, follow MVVM pattern and understand your requirements and do the design. Since you need something from a child user control from a parent user control, a best approach is to have a ViewModel bind to parent and child and access child view model in parent viewmodel and do "what ever you want".
I have a wpf user control that is hosted by a third party application as a non-modal dockable window. I would like to trigger an event with the window gets focus or when the mouse enters the window. This is a MVVM design.
How do I bind the event handler of the Grid (not datagrid) or the UserControl to a method on the viewmodel.
I want to avoid the xaml.cs code since I have to cast the datacontext into the expected viewmodel to make the call.
<UserControl x:Class="MVVMWithCommand.ChartExtentView"
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:MVVMWithCommand"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" GotFocus="UserControl_GotFocus">
<UserControl.DataContext>
<local:MyViewModel/>
</UserControl.DataContext>
<Grid GotFocus="Grid_GotFocus">
There were two problems combined. The solution in the link didn't work because of another problem.
This only partially anwsered the question
WPF Binding UI events to commands in ViewModel
combined with this it did:
Could not load file or assembly 'System.Windows.Interactivity'
I have XAML like this which lets me add in a 3rd Party map control
<UserControl x:Class="AssemblyName.Views.CustomMapView"
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:AssemblyName.Views"
xmlns:ioc="clr-namespace:AssemblyName.Ioc"
xmlns:esri="http://schemas.esri.com/arcgis/runtime/2013"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
ioc:ViewModelLocator.AutoWireViewModel="True">
<esri:MapView x:Name="customMapView">
<esri:Map x:Name="customMap">
<esri:ArcGISTiledMapServiceLayer ID="BaseMap" ServiceUri="http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer"/>
</esri:Map>
</esri:MapView>
</UserControl>
All my business logic which happens in the ViewModel, needs to interact with this control and make it do things. Ideally, I would like the the View to have no idea of what type of control it is. I do this all the time with UserControls by making an entry in the XAML like:
<ContentControl Name="menuControl" Content="{Binding MenuControl}"/>
then the ViewModel can set whatever "Menu Control" object that inherits from ContentControl.
since the customMapView doesn't inherit from ContentControl, I can't use the method above that I normally use. It inherits from Control.
Is there a way I can put in a standard <control/> and assign my map control to it?
Basically, I just want to interact with this Map object in the ViewModel in the most decoupled way possible.
As stated on the Content property description of the ContentControl class :
Because the Content property is of type Object, there are no
restrictions on what you can put in a ContentControl.The Content is
displayed by a ContentPresenter, which is in the ControlTemplate of
the ContentControl. Every ContentControl type in WPF has a
ContentPresenter in its default ControlTemplate
So you can still bind your Content property like you used to :
<ContentControl Content="{Binding MyDisplayedControl}"/>
Why not just inherit from ContentControl? It obviously has content.
Then Create a template for your control which contains a ContentControl who is bound by
<ContentControl Content="{Binding RelativeSource="{RelativeSource Mode=TemplatedParent}, Path=Content}"/>
I think thats right anyhow.. i'm on my phone. Man I love Intellisense..
Anyhow, Specifically setting the content of a content control to another control seems redundant.
I am new to WPF so please understand:
I have a class of usercontrol that implements a screen (dialog) with a grid that contains controls. My code behind file performs a series of checks prior to opening the dialog. If the conditions aren't met, I want to destroy/exit/unload/close the usercontrol. I am using Windows and it seems that I cannot find the call to close the usercontrol. I read up on the questions that had answers such as closing from the parent... however when I try to find the parent via this.Parent, it returns null.
Any advice?
If your conditions aren't met, and you don't even show the usercontrol - don't initialize it.
If you can't avoid that, you have the option of calling Dispose() or letting the GC handle it.
To get the parent from a usercontrol I use this
var parentWindow = Window.GetWindow(this);
But I agree with Andreas if the conditions are not met don't even load it.
A thought could you bind the grids contents remove the usercontrol from the bound object maybe .
Jim
I am guessing you have added your user control in the xaml. That is why you need to even worry about unloading it. Try loading it in the code instead. have a container in your xaml such as a stack panel to hold the user control.
And do not load it unless you conditions aren't met.
eg:
xaml;
<UserControl x:Class="UserControl2"
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"
>
<Grid>
<StackPanel x:Name="mypanel">
</StackPanel>
</Grid>
</UserControl>
code;
if(conditions are true) then
Dim myusercontrol = New ucMyControl()
Me.mypanel.Children.Add(myusercontrol)
end if
I have a tab control that is dynamically populated with tabs that contain user controls of various sizes. When a tab is opened I want the window to automatically resize to a size that makes sense given the active user control. Is there a clean way to do this?
I'm using a standard mvvm pattern.
Use the SizeToContent property on the Window class.
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
SizeToContent='Width'>
<Grid>
<Button Width='200' Content='The Button' />
</Grid>
</Window>