Force UI redraw after loading new resource files - vb.net

I have defined 2 themes (Resource files containing colours - .xaml), one in the resource dictionary on app load and one added on a button click by the following code:
Application.Current.Resources.MergedDictionaries.Clear()
Dim lightTheme As New ResourceDictionary()
Dim lightThemeUri As New Uri("/MyApp.UI;component/Assets/ColourResourcesLight.xaml", UriKind.Relative)
lightTheme.Source = lightThemeUri
Application.Current.Resources.MergedDictionaries.Add(lightTheme)
The colours in the new light theme are defined with the same key as the dark theme (loaded when app loads). My controls are then bound to this key with a staticResource.
After the new resource file loads i would like to somehow update / force a redraw of the whole UI to allow my new theme to display. This works on the controls contained in pages that i then navigate to, however it does not update my navigation bar (Main Page). Every other page is loaded into a container on the main page.
I would like the navigation bar to also update.
Was wondering what the best way to do this was, i have tried updating the bindings by using :
Public Shared Sub ForceControlRebind(cntrl As Control, depprop As DependencyProperty)
Try
Dim BindExp As BindingExpression = cntrl.GetBindingExpression(depprop)
Dim Bind As Binding = BindExp.ParentBinding
cntrl.SetBinding(depprop, Bind)
Catch generatedExceptionName As Exception
Throw
End Try
End Sub
However the BindExp always returns nothing.
I have also tried forcing a UI redraw by using:
mainpage.InvalidateMeasure()
mainpage.InvalidateArrange()
mainpage.UpdateLayout()
I know the resource file is properly loaded as the properties have updated when i step into the controls

Related

VSCT: Place Search Textbox below the toolwindow toolbar

I have made a toolbar that has a Search Textbox, using the visual studio built in search for the toolwindowpane: https://learn.microsoft.com/pt-pt/previous-versions/visualstudio/visual-studio-2015/extensibility/adding-search-to-a-tool-window?view=vs-2015&redirectedfrom=MSDN
That is working just fine right now after overriding the methods, however i also added a toolbar to the toolwindow from the vsct file, however it is positioning the search and the toolbar in the same row:
Is there any way to position the search bar underneath the toolbar just like the solution explorer in visual studio? If not, is there a way to decrease the toolbar size so it uses the minimum space so it doesn't look weird like in the picture?
Thank you.
EDIT: Constructor of the class that inherits ToolWindowPane:
public CpcObjectsWindow() : base(null)
{
this.Caption = "CPC Objects";
// This is the user control hosted by the tool window; Note that, even if this class implements IDisposable,
// we are not calling Dispose on this object. This is because ToolWindowPane calls Dispose on
// the object returned by the Content property.
this.Content = new CpcObjectsWindowControl();
this.ToolBar = new CommandID(new Guid(CpcExtensionPackage.guidCpcExtensionPackageCmdSet), CpcExtensionPackage.cpcObjectsToolbar);
this.ToolBarLocation = (int)VSTWT_LOCATION.VSTWT_TOP;
}
I tried to add search to a tool window , a search control appears at the top of the tool window.
I tried to search form the ToolWindowPane Class but there is not any property can set the size of search bar. I think that you can submit a feature request on DC.

Implementing Detachable Panel in UWP App

I have an Image in a grid where I display some custom content by setting the Image's source to a WritableBitmap and updating the bitmap. What I want to do is to implement a "detach" button that will put my Image on a separate window allowing the user to move it to a different screen, resize it etc. independent of my main app window. If the new window is closed, I would like to bring it back to its original spot. While the Image is on the new window, I want to continuously update it with new content via updating source bitmap (as it would have been before it was detached).
I initially thought I would be able to create a new window and "move" my Image control there by first removing it from its original parent then adding it as a child to a layout in the new window. I used the code below:
CoreApplicationView^ newCoreView = CoreApplication::CreateNewView();
int mainViewId = Windows::UI::ViewManagement::ApplicationView::GetApplicationViewIdForWindow(
CoreApplication::MainView->CoreWindow);
uint indexOfObjectToDetach = -1;
bool found = originalGrid->Children->IndexOf(imageToMove, &indexOfObjectToDetach);
if(found)
{
myGrid->Children->RemoveAt(indexOfObjectToDetach);
}
DispatchedHandler^ dispatchHandler = ref new DispatchedHandler([this, mainViewId]()
{
newView_ = Windows::UI::ViewManagement::ApplicationView::GetForCurrentView();
Windows::UI::Xaml::Controls::StackPanel^ newWindowGrid = ref new Windows::UI::Xaml::Controls::StackPanel();
Window::Current->Content = newWindowGrid;
Window::Current->Activate();
newWindowGrid->Children->Append(imageToMove); // Add to new parent
});
create_task(newCoreView->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, dispatchHandler)).then([this, mainViewId]()
{
auto a = newView_->Id;
create_task(ApplicationViewSwitcher::TryShowAsStandaloneAsync(a, ViewSizePreference::Default, mainViewId, ViewSizePreference::Default));
});
However in the line where I add the Image to its new parent, I get an Interface was marshalled for a different thread error. Upon more reading, this is due to the fact that each new window is in its own thread and I'm moving an object to another thread.
I am new to UWP and I am not sure how to approach implementing this UI behavior. How do I access/transfer my state in one view to another ?
The problem is indeed the fact that each application view in UWP has its own thread and its own UI dispatcher. When you create a control, it is tied to the UI thread it was created on, hence you cannot place it onto another application view.
The solution is to create the new Image next to the StackPanel within the new view's UI thread. I don't really use C++, but in C# I would implement it as follows:
await newCoreView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
StackPanel panel = new StackPanel();
Image image = new Image();
panel.Children.Add( panel );
image.Source = ...; //your source
Window.Current.Content = frame;
Window.Current.Activate();
newViewId = ApplicationView.GetForCurrentView().Id;
});
To further clarify - you can safely "transfer" normal data types into other view, the problem is mainly with the UI-tied types like controls, pages, etc.

How to open a winform at same location and with same size of its parent in vb.net? Parent may be Winform or UserControl

Dim popCus As New PopCustomer()
popCus.StartPosition = FormStartPosition.Manual
popCus.Location = New Point(ctrList.Location)
popCus.Size = New Size(ctrList.Size)
popCus.ShowDialog()
Here ctrList is a UserControl's object and PopCustomer if a Winform.
I want open PopCustomer at same location and same size of ctrList.
The problem there is that the Location of the UserControl is relative to its own parent while for the form it's relative to the screen.
If you change this:
popCus.Location = New Point(ctrList.Location)
to this:
popCus.Location = ctrList.PointToScreen(Point.Empty)
then you'll get the effect you want. You can actually use the same code for a form so that means that you can write a single method with a Control parameter and then use that parameter to set the Location and Size of the new form. You can then call that method and pass either a form or a user control as an argument.

Visual Basic PictureBox Panel Flicker

I am making a simple game that (for the main part) consists of a Panel with a grid of 32 PictureBoxes inside, each with a BackgroundImage. You click on a "tile" and it flips revealing a picture. My problem is that when the Form Loads, I can see it drawing. I see the Panel .. then empty PictureBoxes, then finally it fills in the PictureBoxes with the BackgroundImages.
I've turned DoubleBuffer to True for the Form, and I've also added the following:
Private Sub UseDoubleBuffer()
Me.SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.UserPaint Or ControlStyles.DoubleBuffer, True)
Me.UpdateStyles()
End Sub
Which I call when the Form Loads. I'm not sure what else I can do? I want it to just 'pop' onto the screen. Why isn't the DoubleBuffer working? Do I need to code the panel manually? I was trying to avoid that as it's obviously easier to just drag and drop into the Form, but if I need to, I will.
I can't post screenshots apparently, as my rep isn't high enough yet, but believe me, it looks hideous, and I do want to make this as sleek as I possible can. Any ideas?
Try creating flicker free custom panel controls:
Here are the steps to use this control:
1. Add new class "NonFlickerPanel" to your C# application.
2. Replace autogenerated class code with C# code shown below.
3. Use NonFlickerPanel object instead of Panel object in your application.
public partial class NonFlickerPanel : Panel
{
public NonFlickerPanel() : base()
{
this.SetStyle(ControlStyles.AllPaintingInWmPaint,
ControlStyles.UserPaint
ControlStyles.OptimizedDoubleBuffer,
true);
}
}
Try making the picture boxes invisible (.visible = false) until they're all loaded, then set visible to true for all of them.

Unable to dynamically load a control into a SplitContainer panel

I have placed a SplitContainer control onto a form. I have a custom control inside panel 1. This custom control is the container for another user-control.
There is a TreeView control inside this user-control. I am trying to load another user-control onto panel 2 upon selection of a node in the tree view. But its not getting loaded. Am i missing something?
The code for loading the control is given below:
Dim ucImportExcel1 As New ucImportExcel()
frmMain.SplitContainer1.Panel2.Controls.Add(ucImportExcel1)
ucImportExcel1.Dock = DockStyle.Fill
An addition to the above: In the same treeview selection event
For the code below it sets the form text:
me.parentform.text = "Sample Text 1"
Whereas if use this code, nothing happens:
frmmain.text = "Sample Text 2"
When referred by a Directcast, it solved the problem:
DirectCast(Me.ParentForm.Controls.Item("SplitContainer1"), System.Windows.Forms.SplitContainer).Panel2.Controls.Add(ucImportExcel1)