DirectCast any window, not only main window? - wpf

I've been trying to edit variables in other windows like in VB.NET using DirectCast. This seems to be working very well with the main window, as I use
Private Main As MainWindow = DirectCast(Application.Current.MainWindow, MainWindow)
But, I am unable to find a way to use this with a window other than the main one. For now, I am stuck using this
Dim WindowOne As New Window1
WindowOne.Show()
This works, but I would rather not have to create a new instance of the window each time I want it to open. I have tried using
Private WindowOne As Window1 = DirectCast(Application.Current.Windows.OfType(Of Window1).First(), Window1)
but it always gives me an error saying that "The sequence contains no elements".
Is there any other way to do this? What am I doing wrong?

The correct syntax is below.
Private WindowOne As Window1 = Application.Current.Windows.OfType(Of Window1)().FirstOrDefault()
If Not WindowOne Is Nothing Then
'object is available here
End If

Related

getting values from a second window to the main window in wpf

I have a wpf application which will work minimized. The application will show a second window when system wakes up from sleep. In the second window there is a combobox and a button. when i click on the button it should set the value of a variable in the mainwindow with the value of combobox. But the problem is the variable in mainwindow is not accessible in second window. How to do this?? I searched a lot in net. But unable to find a working solution. Any suggestions??
You could use Event / delegate approach to get it:
A code snippet to sum-up:
In your First window when creating the second one do
Window1 win = new Window1();
win.GetEvent += win_GetEvent;
win.ShowDialog();
And in the second window you have:
public object ValueToGet;
public delegate object GetValueDelegate(object _value);
public event GetValueDelegate GetEvent;
public Window1()
{
InitializeComponent();
GetEvent.Invoke(ValueToGet);
}
Well I don't know which your specific requirment but just to intreduce the approach

To set the owner property for WPF window

I am Working on creating addin for Autodesk Inventor, I have class lib project in that I will show a wpf window on button click, that works great. However, I could not set the owner property for my window.. In my research I came to know that we need to get the parent window object..
If you're not able to get parent window, you can try setting the parent using window handle.
I'm not familiar with Autodesk Inventor and how you create plugin for the application so I don't know if you can get window handle but I guess you could know process id or window caption/title or some other information that can help you get the parent window handle (you should Google how to get window handle). Once you have handle of parent window you can set it as an owner of your window using WindowInteropHelper.
Here's just a sample how to use WindowInteropHelper:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
IntPtr parentWindowHandler = IntPtr.Zero;
// I'll just look for notepad window so I can demonstrate (remember to run notepad before running this sample code :))
foreach (Process pList in Process.GetProcesses())
{
if (pList.MainWindowTitle.Contains("Notepad"))
{
parentWindowHandler = pList.MainWindowHandle;
break;
}
}
var interop = new WindowInteropHelper(this);
interop.EnsureHandle();
// this is it
interop.Owner = parentWindowHandler;
// i'll use this to check if owner is set
// if it's set MainWindow will be shown at the center of notepad window
WindowStartupLocation = System.Windows.WindowStartupLocation.CenterOwner;
}
}
I'm just reiterating the example that user1018735 gave. I develop Inventor Add-ins so I modified the code above to make sure I am always working with the correct Inventor session since multiple instances of Inventor can be open at once. I do this by passing my already known application object to my form through the _App parameter; then since the process MainWindowTitle is always the same as the applications caption I match the two.
I'm running this in a WPF Class Library # VB.Net 4.5.1.
Here is a peek at my code that works in Inventor 2014...
Public Sub New(ByVal _App As Inventor.Application)
'This call is required by the designer.
InitializeComponent()
'Find the Inventor Window Handle.
Dim InvWndHnd As IntPtr = IntPtr.Zero
'Search the process list for the matching Inventor application.
For Each pList As Process In Process.GetProcesses()
If pList.MainWindowTitle.Contains(_App.Caption) Then
InvWndHnd = pList.MainWindowHandle
Exit For
End If
Next
Dim InvWndIrp = New WindowInteropHelper(Me)
InvWndIrp.EnsureHandle()
InvWndIrp.Owner = InvWndHnd
...
// Create a window and make this window its owner
Window ownedWindow = new Window();
ownedWindow.Owner = this;
ownedWindow.Show();

datagrid property list is not available in VB.net

I have a datagrid, and i use to access its values like:
userName = frm_main.datagrid1.Item(1, 0).Value.ToString
however this thing is perfectly fine, but now i just created a new form and when i tried to access this Item property of datagrid1 its not available.
Does anyone have idea, whats the issue?
To be more precise when i am typing it shows me frm_main as highlighted like class in sky blue color.
If you're trying to access frm_main from a different form, it has to have an instance of frm_main to work with. Without an existing instance of frm_main for it to work with, as far as that form is concerned frm_main doesn't exist.
I'm guessing that you're initializing that second form from somewhere within frm_main? If so, when you initialize it, do something like this:
Form2 f = new Form2(this);
f.Show();
And in the code for Form2, put in:
private frm_main Main;
Public Form2(frm_main _Main) { Main = _Main; InitializeComponent(); }
This gives it the existing instance of frm_main to work with and access to all of the controls within it. You would just refer to it as Main, or whatever variable name you would like to give it in code.
*edit:*I just realized this was for VB.Net, the VB code for this would be
Dim f As New Form2(Me)
f.Show()
and then create your own constructor for Form2
Dim Main As Form1
Public Sub New(ByRef _Main As Form1)
Main = _Main
InitializeComponent()
End Sub
That should do it!

I can't use Window.Show despite of creating new Window instance

here's the problem:
In my WPF application I used to load/parse my .xaml files using XamlReader.Load Method to open a window in my application.
Codefragment of my function which return the window:
Dim win As New Window()
Dim myObject As Object
Dim xml As XmlReader = XmlReader.Create("mysample.xaml")
myObject = System.Windows.Markup.XamlReader.Load(xml)
win = CType(myObject, Window)
Return win
I use this to display all my different windows the user wants to see.
I open the window with win.Show and close it, when user switch to another window with win.Close. It works well!
Now to increase the performance I plan to do all the XAMLReader.Load at Application Start and store the information into a Dictionary:
Private Shared windict As Dictionary(Of String, Object)
Public Shared Sub ConvertXAMLToWindow(ByVal formName As String)
windict = New Dictionary(Of String, Object)
Dim myObject As Object
Dim xml As XmlReader = XmlReader.Create(formName)
myObject = System.Windows.Markup.XamlReader.Load(xml)
windict.Add(formName, myObject)
End Sub
Then I want to use that information when calling windows:
If windict.ContainsKey(formName) Then
Dim win As New Window()
Dim myObject As Object
myObject = windict(formName)
win = CType(myObject, Window)
Return win
End If
Now
This works well, but when I use win.Close to close my window I get an error when trying to open it again with win.Show, although I create an new instance of Window?
System.InvalidOperationException
Cannot set Visibility or call Show, ShowDialog... after a Window has
closed.
But it works when I don't use the Dictionary Method but the XAMLReader.Load directly - any ideas whats going on ? Somehow the window I get by returning XamlReader.Load seems different than the stored information from the dict?? Am I missing somehting? Thanks in advance!
You could use Hide() instead of Close()
Hide hides the Form, so instead of disposing of the form (and its controls) you make it invisible. Show will make it visible again.
Be careful though, the form in the dictionary will still hold the state from the previous time it was used.

Printing in WPF

I've created some windows in wpf that I need to print to one xps document. Each window opens, loads the relevant data and then immediately closes. Currently I use the below code to create the xps:
Using doc = New XpsDocument(TempLoc, FileAccess.Write)
Dim writer = XpsDocument.CreateXpsDocumentWriter(doc)
Dim collator = writer.CreateVisualsCollator()
Dim Window1 As Window1 = New Window1()
Window1.ShowDialog()
Dim Window2 As Window2 = New Window2()
Window2.ShowDialog()
Dim WindowX As WindowX = New WindowX()
WindowX.ShowDialog()
collator.BeginBatchWrite()
collator.Write(Window1)
collator.Write(Window2)
collator.Write(WindowX)
collator.EndBatchWrite()
End Using
Dim doc2 = New XpsDocument(TempLoc, FileAccess.Read)
Dim seq = doc2.GetFixedDocumentSequence()
Dim window = New Window()
window.Content = New DocumentViewer() With {.Document = seq}
window.ShowDialog()
doc2.Close()
However the trouble with this approach is that the area printed varies between machines - I assume this is due to the local screen size being used etc.
Is it possible to make the program print the full window independent of the computer its on by modifying this code? Alternativly is there a better way to approach this problem?
Thanks for any help
I print with FixedDocuments by either appending or adding placed UIElements. I posted the full source code to my helper class here. You may find that breaking it down by UIElements gives you much better control over your exact printed output, though yes, it requires you to separate printing code instead of just emitting your window.
I've used this helper class to create some very nicely formated multi-page reports that always come out the same on every computer.

Resources