How to set the usercontrol for ribbon window in WPF? - c#

First I've created a WPF application, then I added new RibbonWindows to the application, and called it RibbonWindow1. Now I want to set the content of the ribbon control via the code belowe and show the ribbon:
RibbonWindow1 ribWindow = new RibbonWindow1
{
Title = "This is a ribbon window",
Content = new UserControl1()
};
ribWindow.ShowDialog();
But I can't see the ribbon bar. If I remove content the ribbon will be shown, also if I use drag and drop I can show it, but I want to do it via simple code, dynamically.
If I can dock the related control in a specific grid cell it will be helpful to me. Any suggestions?

In my little experience with RibbonWindow, i saw that ribbon is part of the content of the ribbonwindow itself. So, a solution could be to expose a public method for the ribbon window that set your usercontrol, like this:
<ribbon:RibbonWindow ...>
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ribbon:Ribbon x:Name="Ribbon" />
//add a container for your usercontrol
<Grid Name="contentPlaceHolder" Grid.Row="1"></Grid>
</Grid>
and in the code you can set a method like
public void SetControl(UserControl uc)
{
this.contentPlaceHolder.Content = uc;
}

Related

C# WPF How to navigate to an existing page from the MainWindow?

I have a task which has to implement the MVVM pattern.
I have a MainWindow with a button, successfully tied it up to a working and tested command.
My goal is to navigate to an existing Page on button click, but the problem is:
-NullReferenceException()
Corresponding MainWindow.xaml part
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Frame x:Name="MainFrame" NavigationUIVisibility="Hidden" Content="{Binding MainFrame}" ></Frame>
ETC
Corresponding ViewModels clickCommand:
private void ExecuteMethod(object parameter)
{
View.Home homePage = new View.Home();
mainFrame.Content = homePage;
MainFrame.Navigate(homePage);
}
Page to be loaded is an existing page with several controls in it, yet I fail to even navigate to there, since
mainFrame.Content = homePage;
throws a NullReferenceException(object reference not set to an instance of an object)
What am I missing?

C# wpf web control

is any way to open a web browser(visible?) in specific browser and do action like clic button, search etc. i try
WebBrowser web = new WebBrowser();
web.Navigate(new Uri("https://www.google.com/"));
but i didnt see it. I too know i can do something like that
System.Diagnostics.Process.Start("chrome.exe","http://www.google.com");
but how then make action there control it? Or the only way is open browse in wpf and show it on some king of window.
The best place to actually start learning how to utilize the different Class Controls at our disposal from the .NET environment is reading their documentation!
WebBrowserClass
They show a relative simple example of how to achieve what you want, with the creation of the webbrowser in XAML. In this XAML, they define a TextBox so you can introduce your absolute path, but also a button to perform the search when you click on it.
<Grid x:Name="MainGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<TextBox x:Name="addressTextBox" Width="200" />
<Button Click="Button_Click">Go</Button>
</StackPanel>
<WebBrowser Grid.Row="1" x:Name="myWebBrowser" />
</Grid>
I changed the XAML part a bit, so you don't have your WebBrowser with limited Height and instead have it occupied most of the screen real estate.
PS. In all honesty i cannot pinpoint why your code-behind implementation on the WebBrowser is not working though.

MAF Plugin UI content scrolling outside of bounds in main application

A little bit of background first, I have an application that uses the Microsoft AddIn Framework (MAF) that gets a WPF UI from the plugins (You can follow this Microsoft example to create one). This is up and working fine until the plugin content is large enough that the main form needs to scroll. When this happens, it scrolls outside of the bounds that it should.
In the image, you'll notice that the Plugin Label Top goes over Main Label Top when you scroll down some and at the bottom you'll only see Plugin Label Bottom. My code for the main form is the following:
<Window x:Class="WpfAddinTest.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:WpfAddinTest"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525" Background="DarkGray">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="25"/>
<RowDefinition/>
<RowDefinition Height="25"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Content="Main Label Top"/>
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
<ContentControl Name="PluginHolder"/>
</ScrollViewer>
<Label Grid.Row="2" Content="Main Label Bottom"/>
</Grid>
</Window>
ContentControl is what houses the plugin UI, I don't understand why the plugin UI is going over it's parent controls. I've tried housing it in different types of controls, such as a DockPanel and Grid, everything acts the same way.
Is there a special way to get this to function correctly?
If more code is needed, I'm happy to post it, https://github.com/middas/WpfAddInTest is my complete sample project that demonstrates this.
EDIT: Loading up the form in WPF Inspector, all I can see is an AddInHost control, it doesn't show any of the individual controls inside the ContentControl. Does this have something to do with it?
EDIT 2: In trying anything I can think of, I was thinking that maybe it wasn't getting the right height when it placed the control in, so I had the plugin return the desired height and set the Height of the ContentPlaceholder manually based on what was returned; no luck. Here is what I tried:
I updated the AddIn contracts from GetInt() to GetHeight() and on the Plugin I have this method now:
public double GetHeight()
{
_Control.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
return _Control.DesiredSize.Height;
}
Then on the hosting form, I have this now:
public MainWindow()
{
_PluginPath = System.IO.Path.Combine(Environment.CurrentDirectory, "Pipeline");
_AddInPath = System.IO.Path.Combine(_PluginPath, "AddIns");
InitializeComponent();
var warnings = new List<string>(AddInStore.Update(_PluginPath));
_PluginToken = AddInStore.FindAddIns(typeof(IPlugin), _PluginPath, _AddInPath).FirstOrDefault();
_Plugin = _PluginToken.Activate<IPlugin>(AddInSecurityLevel.FullTrust);
var control = _Plugin.GetControl();
PluginHolder.Height = _Plugin.GetHeight();
PluginHolder.Content = control;
}
EDIT 3: Attempting to force the ZIndex doesn't seem to affect it either.
Panel.SetZIndex(control, -1);
I believe I've finally figured out the issue. I believe the problem is because the plugin UI is outside of the AppDomain, the ScrollViewer doesn't know how to clip the content properly. What I finally did that worked was create a callback to the main UI that the plugin can use to be given a height that it needs to fit in. If the plugin requires scrolling, the plugin can then handle it with it's own ScrollViewer.
Here is the updated Contract:
[AddInContract]
public interface IPluginContract : IContract
{
INativeHandleContract GetControl();
double GetHeight();
void SetHostCallback(IHostCallbackContract callback);
}
IHostCallbackContract:
public interface IHostCallbackContract : IContract
{
double GetHeight();
}
Now before the plugin returns the Control it can set the Height given by the main form:
public FrameworkElement GetControl()
{
if (_Callback != null)
{
_Control.SetHeight(_Callback.GetHeight());
}
return _Control;
}
I have updated my Git repo (https://github.com/middas/WpfAddInTest) with the entire working solution. The only issue with it now is that the scrolling isn't double buffered so it flickers. I'll have to live with that though since it doesn't appear there is a way to fix though due to WPF rendering via DirectX.

Control like debug Object list in WPF

I want to create a WPF control which looks like control which appears while we debug .NET code. I.e. control like the window which shows all the property/value and have top and bottom arrow, clicking on which list scrolls up/down. (I am looking for control which have Scroll bar in this style).
To be more specific, I want to make a control like a Panel in which I can display controls/text and which have sroll button in middle like it appears in debug window as shown in Image link.
Link is having sample of control I am trying to make.
http://www.use.com/supersize.pl?set=11a2085f136b99d6869c
Any help will be appreciated.
It sounds like you want to use the WPF Visualizer that comes with Visual Studio. You can access it in debug mode once execution has hit a break point. It displays every property and value for every item in the visual tree. You can find out more from the How to: Use the WPF Tree Visualizer page on MSDN.
The control you wanted probably like this
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="25"/>
<RowDefinition Height="*"/>
<RowDefinition Height="25"/>
</Grid.RowDefinitions>
<RepeatButton>Up</RepeatButton>
<ScrollViewer Grid.Row="1" x:Name="sv" VerticalScrollBarVisibility="Hidden">
<Rectangle Height="700" Fill="Black"/>
</ScrollViewer>
<RepeatButton Grid.Row="2">Down</RepeatButton>
</Grid>
also you should control scrollview in codebehind via click eventhandler of RepeatButton.

Silverlight: Show the same controls on every page

I'm building a SL4 app. I have two controls, a top search bar and a bottom favorites bar, that I'd like to be present on every page. I'm not sure what the best way to do this is.
My current approach uses a nav frame as the root visual:
App.xaml.cs:
this.RootVisual = new NavFrame();
NevFrame.xaml:
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<my:TopSearchBar x:Name="topSearchBar" Grid.Row="0"/>
<navigation:Frame x:Name="navigationFrame" Source="/HomePage.xaml" Grid.Row="1"/>
<my:BottomFavoritesBar x:Name="bottomFavoritesBar" Grid.Row="2"/>
</Grid>
Then, I'd change pages within the Frame, leaving the persistent elements in place. Is this the correct approach, or is there some other preferred pattern?
However, if I do this, I'm not sure how to let the TopSearchBar and BottomFavoritesBar user controls do navigation. (In general, I'm not sure how to do navigation directly from a UserControl.)
When TopSearchBar was a member of each page, I'd have this code on each page's code-behind:
topSearchBar.ParentPage = this;
TopSearchBar could then use this reference to do navigation:
ParentPage.NavigationService.Navigate(new Uri("/SearchPage.xaml?q=" + searchBox.Text, UriKind.Relative));
Is there a better way to do this? It feels somewhat awkward. If navigation requires a reference to a page, how can I pass that reference from NavFrame?
The appropriate approach is to add a dependency property to both the TopSearchBar and BottomFavoritesBar called "Navigator" (or whatever you prefer) that has the type INavigate.
Your xaml would look like this:-
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<my:TopSearchBar x:Name="topSearchBar" Grid.Row="0" Navigator="{Binding ElementName=navigationFrame}"/>
<navigation:Frame x:Name="navigationFrame" Source="/HomePage.xaml" Grid.Row="1"/>
<my:BottomFavoritesBar x:Name="bottomFavoritesBar" Grid.Row="2" Navigator="{Binding ElementName=navigationFrame}" />
</Grid>
Now in your two Bar user controls navigation is simply:-
Navigator.Navigate(new Uri("/SearchPage.xaml?q=" + searchBox.Text, UriKind.Relative));
Edit
To create the dependency properties add this to your TopSearchBar class:-
public INavigate Navigator
{
get { return GetValue(NavigatorProperty) as INavigate; }
set { SetValue(NavigatorProperty, value); }
}
public static readonly DependencyProperty NavigatorProperty =
DependencyProperty.Register(
"Navigator",
typeof(INavigate),
typeof(TopSearchBar),
new PropertyMetadata(null));
Duplicate this in your BottomFavoritesBar class but change the reference to TopSearchBar.
I suggest looking in to Prism CAL Pattern
This way you can create regions for your containers and the region(s) you want changed from page to page... it's simple, you just swap the new one to replace the old one while the others remain in place. It's a much more streamlined approach in my opinion.
http://development-guides.silverbaylabs.org/Video/Silverlight-Prism

Categories