Access controls on User Control - wpf

I have a user control, and I need to access a label on that user control from another Window.. example... simply change the text of a label. Example..
Usercontrol.label1.content = "Got it"
I can access any control on the MainWindow by doing the following:
Public main As MainWindow = DirectCast(Application.Current.MainWindow, MainWindow)
How do I do this for a User Control in WPF?

To access MainWindow:
Dim Main = TryCast(Application.Current.MainWindow, MainWindow);
If your UserControl defined statically like this:
<local:UserControl1 x:Name="uc" />
You can just use it's name like: Main.uc.label1.Text = "Hello World"
If your UserControl is dynamically added to a container, try following:
If your UserControl is in a Border:
Dim control = Main.MyBorder.Child as MyUserControl
control.label1.Text = "Hello World"
If there are multiple UserControls in your container such as (StackPanel/Grid/Wrappanel etc):
Dim controls = Main.MyStackPanel.Childern.OfType(Of MyUserControl)()
For Each control In controls
control.label1.Text = "Hello World"
Next
Even though you can get the exact UserControl you want by checking the variables it has!
Dim control = Main.MyStackPanel.Childern.OfType(Of MyUserControl)().Where(Function(x) x.label1.Text = "myLabel").FirstOrDefault()
//You can access any variable that exists in your UserControl by 'x'
control.label1.Text = "Hello World"

Once you have got a reference to the window in which the UserControl resides, you could access it using this reference.
So if the UserControl is for example defined in a window called Window1, here is how you could access it from another window:
Dim window1 As Window1 = Application.Current.Windows.OfType(Of Window1).FirstOrDefault()
window1.uc.label1.Text = "1"
This of course assumes that there is a Window1 opened and visible on the screen and that you given the UserControl element an x:Name in the XAML markup of the window:
<local:UserControl1 x:Name="uc" />

Related

Update bindings for control created in code

I have created a UserControl, which has some values bound to its view model.
I want to create an instance of that UserControl, provide it with a view model, and save it to an image without actually showing it on screen anywhere.
The problem is that when I create an instance of the UserControl and give it its view model, the bindings don't update. So the image that I am saving is the control without any data in it.
How can I force all the bindings to update for a user control that I am creating in code, without actually displaying it on screen?
Here is a short example I wrote:
UserControl1.xaml:
<Grid>
<TextBlock Name="txt" Text="{Binding}" />
</Grid>
UserControl1.xaml.cs
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
internal string GetText()
{
return txt.Text;
}
}
Test.cs
public void Test()
{
UserControl1 uc1 = new UserControl1();
uc1.DataContext = "Test";
Console.WriteLine("The text is " + uc1.GetText());
}
I am expecting it to print out "The text is Test", but it actually prints out "The text is".
I managed to get around the problem by setting the DataContext before calling InitializeComponent. In order to do this, I created a new constructor for my user control that looks like this:
public UserControl1(object viewModel)
{
DataContext = viewModel;
InitializeComponent();
}
If I use this constructor, the bindings will work even if I never show the control on screen.

How can I select tabitem in usercontrol from MainWindow

I would like to ask you, how can I access my usercontrol from MainWindow?
For accessing to MainWindow I'm using :
Dim mw As MainWindow = DirectCast(Application.Current.MainWindow, MainWindow)
I need this because I would like to select particular TabItem from my UserControl. (tabitem.IsSelected= true). UserControl is already placed in Grid on MainWindow as a child.
Thank you in advance
simple way is to create a ReadOnly property in MainWindow returning the user control instance
eg
Public ReadOnly Property MyEmployeeMenu As UserControl
Get
Return Me.employeemenu
End Get
End Property
usage
Dim mw As MainWindow = DirectCast(Application.Current.MainWindow, MainWindow)
Dim empMenu as UserControl = mw.MyEmployeeMenu 'this way you can access the control

Can I add a DependencyProperty on an windows user control?

I'm trying to host a Visio ActiveX object in a WPF application.
To do this, I created a Windows user control project where I add the Visio object. This windows user control is then hosted on an WPF user control in an WindowsFormsHost object.
<WindowsFormsHost Name="wfHost" Grid.Row="1">
<wf:VisioUserControl FileNamePath="?"/>
</WindowsFormsHost>
What I would like to do is to bind the value of the FileNamePath member to the value of a TextBox element which defines the path.
The project follows the MVVM pattern, so there is no way that I can access the VisioUserControl object in my ViewModel.
The solution I was thinking about is to bind the FileNamePath member to the value of the TextBox that contains the path, but it is not a DependencyProperty and it seems that I'm not able to define one in the code behind of the windows user control.
So, is there any workaround to perform this binding?
Thanks in advance.
You can solve this by creating a UserControl that wraps your VisioUserControl (I wrote a simple tutorial on UserControl creation here). You can then add a FileNamePath dependency property to your UserControl. In the property changed handler of this dependency property, set the FileNamePath property on the VisioUserControl that this user control wraps.
Ok I have created an example of a WPF usercontrol that is hosting a Winforms control, with a dependency property that is bound to the winforms control's text property.
public partial class ActiveXObjectHoster : UserControl
{
private static System.Windows.Forms.Label testObject;
public ActiveXObjectHoster()
{
InitializeComponent();
testObject = new System.Windows.Forms.Label();
windowsFormsHost1.Child = testObject;
}
#region Properties
public static DependencyProperty FileNameProperty = DependencyProperty.Register("FileName", typeof(string), typeof(ActiveXObjectHoster), new UIPropertyMetadata("",new PropertyChangedCallback(OnFileNamePropertyChanged)));
public string FileName
{
get { return (string)GetValue(FileNameProperty); }
set
{
SetValue(FileNameProperty, value);
}
}
private static void OnFileNamePropertyChanged(
DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
testObject.Text = (string)e.NewValue;
}
#endregion
}
Here is the xaml of the control (its very simple)
<UserControl xmlns:my="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
x:Class="WPFTestApp2.Controls.ActiveXObjectHoster"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="ObjectHost"
Height="100" Width="100">
<Grid>
<my:WindowsFormsHost x:Name="windowsFormsHost1" />
</Grid>
</UserControl>
What you need to do is change the test object from a Label to whatever Visio object you were using. Then in the property callback change the text property to the filename or whatever property you wanted.
As mentioned above this is done in the code behind, but that is fine for a user control, its completely decoupled from whatever thing is using it, you just need to bind to the filename property of the control.
Here is a link to a project I created showing how the control is used. There is a textbox whos text is bound to the FileName property, which changes the Winforms Labels text.
You can place this in a Winforms Usercontrol if you want to use it in winforms (like you mentioned in your reply to my comment)
Try replacing the label for your control and see if it works.
Why not implement a UserControl to wrap the WindowsFormHost and the Visio user control? Then you cann add a Dependency Property, and implement in the code behind a handler for the PropertyChangedCallback, and appropiately interact with the WinForms control

How can I access one window's control (richtextbox) from another window in wpf?

I'm sure this is something very simple but I can't figure it out. I've searched here and on msdn and have been unable to find the answer. I need to be able to set the richtextboxes selection via richtextbox.Selection.Select(TextPointer1, Textpointer2).
Application.Current contains a collection of all windows in you application, you can get the other window with a query such as
var window2 = Application.Current.Windows
.Cast<Window>()
.FirstOrDefault(window => window is Window2) as Window2;
and then you can reference the control from your code, as in
var richText = window2.MyRichTextBox
Application.Current.Windows.OfType(Of MainWindow).First
You should be able to access controls on Window1 from Window2 code behind, if that's what you want. Generated fields are internal by default.
All you need is to name the control on Window1, like this:
<RichTextBox x:Name="richtextbox" ... />
In Window2 code behind:
var window = new Window1(); // or use the existing instance of Window1
window.richtextbox.Selection.Select(TextPointer1, Textpointer2);
A better option would be to encapsulate select operation in a method in code behind of Window1, to avoid giving away internal. Then you would have:
// Window1.cs
public void Select(int param1, int param2)
{
richtextbox.Selection.Select(param1, param2);
}
// Window2.cs
var window = new Window1(); // or use the existing instance of Window1
window.Select(TextPointer1, Textpointer2);
You cant access the texbox from another window as it is private to that window you can however work around this by exposing the RichTextBox as a public property on your window (hack)
public RichTextBox RichTextBox {
get{
//the RichTextBox would have a property x:Name="richTextbox" in the xaml
return richTextBox;
}
}

WPF window hosting usercontrol

I have a usercontrol that I use to edit some objects in my application.
I have recently come to an instance where I want to pop up a new dialog (window) which will host this usercontrol.
How do I instantiate the new window and pass any properties that need to be set from the window to the usercontrol?
Thanks for your time.
You can simply set the content of your new window to your user control. In code, this would be something like this:
...
MyUserControl userControl = new MyUserControl();
//... set up bindings, etc (probably set up in user control xaml) ...
Window newWindow = new Window();
newWindow.Content = userControl;
newWindow.Show();
...
You need to:
Create some public properties on your dialog Window to pass in the values
Bind your UserControl to those public properties in your dialog Window
Show your dialog Window as dialog when needed
(optional) retrieve values from the window that are two-way bound to your user control
Here's some pseudocode that looks remarkably like C# and XAML:
How to show a window as a dialog:
var myUserControlDialog d = new MyUserControlDialog();
d.NeededValueOne = "hurr";
d.NeededValueTwo = "durr";
d.ShowDialog();
and the source
public class MyUserControlDialog : Window
{
// you need to create these as DependencyProperties
public string NeededValueOne {get;set;}
public string NeededValueTwo {get;set;}
}
and the xaml
<Window x:Class="MyUserControlDialog" xmlns:user="MyAssembly.UserControls">
<!-- ... -->
<user:MyUserControl
NeededValueOne="{Binding NeededValueOne, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
NeededValueTwo="{Binding NeededValueTwo, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
</Window>
you'd do the same thing in your UserControl as you've done in your window to create public properties and then bind to them within the xaml.

Resources