Accessing WPF controls from a hosting WinForm application - wpf

I have a WinForm application in which I am trying to replace my toolbar with a WPF toolbar.
My solution now contains two projects:
A WPF user control project that defines the WPF toolbar
A Windows Form Application that hosts the WPF toolbar
Enabling / disabling buttons, adding items to combos, events handling of toolbar controls will have to be defined in the WinForm application, so in order to have access to them, I did the following:
in the XAML I gave each control in the toolbar a name
In the code I defined a public get property for each control
This works fine, but I was wondering if this is the right approach. Is there a better way to do what I want?
Can you post the XAML of your toolbar? – HighCore
I've made a small example of the XAML of my toolbar as you asked.
<ToolBarTray>
<ToolBar Band="1" BandIndex="1">
<Button Name="btnDoSomething1">
<Image Source="/WpfExampToolbarCtrl;component/Images/DoSomething1.png" />
</Button>
<Button Name="btnDoSomething2">
<Image Source="/WpfExampToolbarCtrl;component/Images/DoSomething2.png" />
</Button>
<Separator />
<Menu>
<MenuItem Header="Create Item">
<MenuItem Header="Item 1" />
<MenuItem Header="Item 2" />
</MenuItem>
</Menu>
<Separator />
<ComboBox Name="comboCategory">
<ComboBoxItem Content="Category 1" IsSelected="True" />
<ComboBoxItem Content="Category 2" />
</ComboBox>
</ToolBar>
</ToolBarTray>
I thought to give each control in the toolbar a name, and in the code behind define a get property for each one. This way I could access each of the toolbar's controls from my the main form of my WinForm application, and do what I want. (Add events, disable/enable controls at runtime, add items to combos at initialization or during runtime, …).
But from what I understand from Kent Boogaart answer this is not the right approach.

I'd sooner have my WPF UI bound to a model. I would then access the model from the Winforms side and manipulate that.
To elaborate: WPF's binding infrastructure is very strong and unlike what you're used to in Winforms. WPF applications tend to follow the MVVM pattern, whereby the view's data context is a view model, and your controls in the view have bindings against properties in your view model.
Thus, what I'm suggesting is you first define a view model, then modify your WPF view to bind to properties on that view model, then access that view model from your Winforms code. Changing properties on that view model from your Winforms code will automatically update the WPF view.

Related

MVVM WPF - Viewmodel commandbinding

Iam using MVVM model and I have three usercontrols in a WPF Main window and each usercontrol has datacontext set to different viewmodels in the xaml.
The main window is also attached to a different viewmodel in the datacontext. Mainwindow has three buttons and should be bound via command binding, How can we bind the main window buttons to corresponding usercontrol view model Icommand via xaml?
It's difficult to tell if this is a good solution because there are a lot of missing details about your application architecture.
Based on the premise "I have a window that contains 3 user controls and I want buttons on the window to activate commands on the viewmodels of the controls", one solution could be:
<Window>
<UserControl Name="Control1" />
<UserControl Name="Control2" />
<UserControl Name="Control3" />
<Button Command="{Binding ElementName="Control1", Path="DataContext.Cmd"}" />
<Button Command="{Binding ElementName="Control2", Path="DataContext.Cmd"}" />
<Button Command="{Binding ElementName="Control3", Path="DataContext.Cmd"}" />
</Window>
This is a bit subjective, but in my opinion viewmodels should not be serving more then one view.
The MainWindow's viewmodel should be totally independent from the UserControl's models. I would suggest using a publish/subscriber pattern for sending "events" through your application that handle widely used functionality (see for example Event Aggregator).
If you can't access the ViewModels via a direct binding from DataContext of the MainWindow (i.e. if the three ViewModels aren't in the MainWindow's ViewModel), you can just do this :
<Button
Name="Button1"
DataContext="{Binding DataContext, ElementName=UserControl1}"
/>
This should work if I understood well what you're asking.

How can I switch Telerik ribbonview elements according to the type of my child viewmodel?

I'm using an MVVM pattern for my WPF application. If the "home" view model, which controls the layout of my application's main window, I have a ChildViewModel property. This holds a viewmodel that can be switched according to what the user is doing. When they select menu items, the child view model switches and the main area of the screen (it's in an Outlook style) switches accordingly.
I do this with a ContentControl and DataTemplate like this: (I'm only showing one of the embeddable views here to keep it short).
<ContentControl Grid.Row="1" Grid.Column="1" Margin="3"
Content="{Binding ChildViewModel}">
<ContentControl.Resources>
<DataTemplate DataType="{x:Type vm:VersionsViewModel}">
<Embeddable:VersionsView />
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
I also want to add a ribbon to my main window, using the Telerik RadRibbonView control. I want this to have some fixed tabs and buttons that are always visible. In addition, I want to add and remove entire tabs, and buttons within existing tabs, according to the type of child view model. I'd like this to be done in the view in a similar manner to the way I've done the content control, above.
Is this possible? I've tried lots of things but got nowhere so far. I know I could do it by creating a huge "super ribbon" and binding visibility properties but this seems cludgey. I could also have multiple ribbons, each containing the common controls, but this would cause a maintenance problem.
In the end I went with the "super ribbon" approach, as I couldn't find any other way.

WPFToolkit:Split button dropdown button disable button

I am using WPF split button which is inherited from
xmlns:extToolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit/extended"
The issue is I want to disable , the button ' the one below(Right side of Button 'Conf' in below 'downarrow present in the below fig) , If user clicks on Left side of the button the rightside should be disabled and the button(leftside) background should change to yellow.please find below the xaml , I am using the wpf split button , dropdown content in this case .please let me know if you have any idea
<extToolkit:SplitButton x:Name="ABCbutton"
VerticalAlignment="Center"
Command="{Binding ACommand}"
FontSize="16>
<TextBlock HorizontalAlignment="Center"
IsEnabled="{Binding IsEnabled, ElementName=AButton}"
Text="A"/>
<extToolkit:SplitButton.DropDownContent>
<StackPanel>
<Button Command="{Binding BCommand}"
Padding="3"
Style="{DynamicResource
DropDownButtonMenuButton}">
<TextBlock Margin="0,3,6,3"
Text="B"/>
</Button>
<Button Command="{Binding BCommand}"
Padding="3"
Style="{DynamicResource
DropDownButtonMenuButton}">
<TextBlock Margin="0,3,6,3"
HorizontalAlignment="Stretch"
Text="C"/>
</Button>
</StackPanel>
</extToolkit:SplitButton.DropDownContent>
</extToolkit:SplitButton>
In a case like this, you will likely be better off creating your own control. The split button can't really handle what you are talking about without a good deal of modification.
Essentially your new control will consist of two buttons, visually styled so that they look like they blend together. Each will have it's own background and enabled property. Add a ViewModel to help control behaviors and set properties, and I think you would be in business. Keep in mind that all of the controls that are supplied in any of the toolkits, frameworks, control packs, etc are made with the primitive types of drawing and framework elements (line, rectangle, border, content presenter, panel, etc) with specialized behavior code.
I end up making a lot of custom controls just because there is not one that perfectly replicates what I want.

How to reuse Menu and Toolbar in different WPF UserControls with adding new buttons?

I'm trying to port current WinForms app to WPF and need help with building WPF class structure.
Currently in WinForms, I have one base class (with Menu, Toolbar, Grid and Context menu) and several inherited classes with different datasources and columns for the grid and additional buttons for menu, toolbar and context menu.
Questions:
What will be the best WPF class structure for my usercontrol to avoid inheritance?
Can I move ToolBar into ResourceDictionary (e.g. ControlTemplate)?
How to add new buttons or to bind commands to existed buttons, if buttons will be specified in a separate resource file?
Any other ideas?
Due to inheritance restrictions in WPF I see only one way to avoid duplicating Menu, Toolbar, etc. - implement base class in C# code only without XAML. And likely I can't use XAML for inherited classes as well (have no idea how to add new buttons in XAML into Toolbar created in base class)
In WPF a Toolbar is an ItemsControl (same for Menu), so it has an ItemsSource property you can bind to your collection of toolbar items.
<Window.Resources>
<DataTemplate x:Key="ItemTemplate1">
<StackPanel>
<TextBlock Text="{Binding Property1}"/>
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid x:Name="LayoutRoot" DataContext="{Binding MyViewModel}">
<ToolBar HorizontalAlignment="Left" VerticalAlignment="Top" ItemTemplate="{DynamicResource ItemTemplate1}" ItemsSource="{Binding ToolbarItems}"/>
</Grid>
In this code, ToolbarItems is an ObservableCollection< MyToolBarItem >, where MyToolbarItem is a viewmodel that represents one toolbar item.
MyToolBarItem could be the base class, with several classes inheriting from it. Then you can use a DataTemplateSelector to use a different template depending on the type of toolbar item it is.
In this way, all your user controls that have a toolbar can use the same templates you define in your dictionary; each toolbar is just bound to a different collection of MyToolBarItems.
If some of that sounds overwhelming, you can read up on some MVVM. It is the design pattern that makes WPF great.

using autocomplete box in silverlight?

i am currently displaying data in the radgrid controls of telerik, i want to add an autotextbox over the column named "Name". how can i do this?
my radgrid only displays data and i want that whenever user enters into textbox a list of name pops up just like in stackoverflow web site.
please help..i have been using silverlight,wcf ria services,telerik controls.
You can use the AutoComplete textbox from the Silverlight 4 Toolkit. The toolkit is an advanced set of controls that are not part of the core Visual Studio library. To download & install, you can head here. Once you have it installed, you add a project reference to System.Windows.Controls add this to your UserControl declaration:
xmlns:input="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Input"
This gives you a reference point for the Silverlight Toolkit, specifically the input controls. Once that's done, here is an example of using the autocomplete textbox:
<input:AutoCompleteBox IsTextCompletionEnabled="False" HorizontalAlignment="Left" ItemsSource="{StaticResource SampleEmployees}" SelectionChanged="OnSelectionChanged"/>
This comes directly from the documentation from the Silverlight Toolkit. Link here. Click the 'AutoCompleteBox' in the left menu (under heading: Input). Once loaded, you can view the XAML/C# by clicking on any one of the items at the bottom of the window, such as 'AutoCompleteBoxSample.xaml' or 'AutoCompleteBoxSample.xaml.cs' This should give you the start/code you're looking for.
In your case, you'll also need to create a cell template for the radgridview. Here's a quick sample of what that might look like:
<radControls:RadGridView x:Name="registerGridView"
AutoGenerateColumns="False">
<radControls:RadGridView.Columns>
<radControls:GridViewToggleRowDetailsColumn />
<radControls:GridViewDataColumn Header="Client" />
<radControls:GridViewDataColumn Header="Site" />
<radControls:GridViewDataColumn Header="Name">
<radControls:GridViewDataColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<input:AutoCompleteBox HorizontalAlignment="Left" ItemsSource="{Binding Names}" SelectionChanged="OnSelectionChanged"/>
</StackPanel>
</DataTemplate>
</radControls:GridViewDataColumn.CellTemplate>
</radControls:GridViewDataColumn>
</radControls:RadGridView.Columns>
</radControls:RadGridView>

Resources