Access to embedded WPF controls in xaml - c#

Lets say I got the following user control:
<UserControl x:Class="MyUserControl">
<tk:DataGrid>
<tk:DataGrid.Columns>
<!-- some columns -->
</tk:DataGrid.Columns>
</tk:DataGrid>
</UserControl>
Actually, I can't define what columns the data grid should have, since I need to use this control in many places, with different columns. Here is what I want to do:
<UserControl x:Class="MyPanel">
<ui:MyUserControl>
<Columns>
<!-- columns that will go into the data grid -->
</Columns>
</ui:MyUserControl>
</UserControl>
Is it possible to achieve this?
P.S: DataGrid.Columns is readonly, it is not possible to bind it to something else.

You can expose a depenency property on the UserControl called Columns which can bind to an internal DataGrid. You would access the property via <ui:MyUserControl.Columns> of course.

As #H.B. said in his solution, you should expose your own dependency property, but just performing binding wouldn't work, since the Columns property is read-only.
What you need to do is handle this in your dependency property's OnChange callback and add/remove columns as necessary. You'll also need to register to your dependency property's CollectionChanged event and possibly the grid's Columns CollectionChanged as well to synchronize the two properties.
Unfortunately, I don't think there's a XAML-only solution for this.

Related

What is different between {binding} and inherit in wpf datacontext?

I have some problems about datacontext binding.
My app has virtualization listbox.
Sometimes Button is not fired dataContextChanged.
So I found this.
<Grid DataContext={Binding ~~>
<Button DataContext={Binding}/>
</Grid>
<Grid DataContext={Binding ~~>
<Button/>
</Grid>
My Code is first one. but It's not fired DataContextChanged sometimes, So I changed code to second one.
snoop said first one is from inherit, and second one is from parentTemplate.
What is different first one and second one?
TL;DR:
SomeProperty={Binding} will bind the SomeProperty to the ENTIRE DataContext object from the parent. SomeProperty does not have to be the DataContext from the child. In this special case I don't think there is any difference, since the DataContext is inherited anyways. You are simply explicitly stating, what is already the default. Discussed here
More Info:
Here is an explanation from the official documentation for
<Button DataContext={Binding}/>
As long as the binding already has a data context (for example, the
inherited data context coming from a parent element), and whatever
item or collection being returned by that context is appropriate for
binding without requiring further path modification, a binding
declaration can have no clauses at all: {Binding}. This is often the
way a binding is specified for data styling, where the binding acts
upon a collection. For more information, see Using Entire Objects as a Binding Source.
and from here
<ListBox ItemsSource="{Binding}"
IsSynchronizedWithCurrentItem="true"/>
The above example uses the empty binding syntax: {Binding}. In this
case, the ListBox inherits the DataContext from a parent DockPanel
element (not shown in this example). When the path is not specified,
the default is to bind to the entire object. In other words, in this
example, the path has been left out because we are binding the
ItemsSource property to the entire object. (See the Binding to
collections section for an in-depth discussion.)
In general, the DataContext is inherited from parent elements. So in your 2nd example the button gets the DataContext from the Grid. Example
"ItemsControl" are special: Example
I don't know what ~~ is, is this meant to be a placeholder?
Some more information on Bindings and Markup Extensions:
Link1
Link2
Link3

WPF and MVVM: bind UserControl to XAML dynamically

seems like a trivial task: i am building a wpf application, using MVVM pattern. what i want is dynamically change part of a view, using different UserControls, dependent on user input.
let's say, i have got 2 UserControls, one with a button, and another with a label.
in main view i have a container for that. following XAML "works":
<GroupBox Header="container" >
<local:UserControlButton />
</GroupBox>
and a UserControl element with buttons pops up. if i change it to another one, it works too.
question is how to feed that groupbox dynamically. if i put something like that in my model view:
private UserControl _myControl;
public UserControl MyControl
{
get
{
return _myControl;
}
set
{
_myControl= value;
InvokePropertyChanged("MyControl");
}
}
and change my view XAML to something like:
<GroupBox Header="container" >
<ItemsControl ItemsSource="{Binding MyControl}" />
</GroupBox>
and feed it from command with usercontrol for button or for label: nothing happens, although "MyControl" variable is set and is "invoke property changed"..
Obviously there are many ways to skin this particular cat - but to answer the question of why it doesn't work you need to look into the ItemsSource property of ItemsControl on MSDN.
The items control is designed to show multiple items, provided through an IEnumerable passed to the ItemsSource property. You are passing a UserControl, so the binding will fail.
For your example, I would change the ItemsControl to a ContentControl and bind the content to your MyControl property. This should then work.
<GroupBox Header="container" >
<ContentControl Content="{Binding MyControl}" />
</GroupBox>
However, I would strongly recommend looking into other ways of doing this - having a control in your VM breaks MVVM to my mind. Depending on what you are doing look at data templates - #Sheridan's link in the comments provides an great description of a way to do it.
Couldn't post this as a comment so adding as answer..
Have a look at this:
Implementing an own "Factory" for reusing Views in WPF
It uses DataTemplates but doesn't require the DataTemplate section for each view. If you potentially have a lot of user controls/views you wish to display or you are reusing through multiple views or you are intending to actually dynamically generate a view (versus just loading an existing user control) then this might suite your needs.

Use Table without messing with DataGrid

Is it possible to make a table having cells bound to several objects (for example, textboxes) without making use of DataGrid?
Example:
<TextBox Text="{Binding Path=FileName}" Width="300"></TextBox>
The DataContext for the textbox's container should contain a Property named FileName
You should note that your property should be wired to notify when it is changed. See the following for more information:
http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx

Binding a method to a column in datagrid WPF

I have a data grid in wpf which is bound to Collection. In one of the columns i want to bind a public method which returns string instead of a property.
Is there a way to resolve this in WPF.
By the way its one way binding.
I'm not entirely sure what you want to do and the advice of the previous two answers may be (and probably are more) appropriate in your scenario but just you answer your question, you can indirectly bind to a method using an ObjectDataProvider.
<Window>
<Window.Resources>
<ObjectDataProvider x:Key="newGuidProvider"
ObjectType="{x:Type Guid}"
MethodName="NewGuid"
/>
</Window.Resources>
...
<TextBlock Text="{Binding Source={StaticResource newGuidProvider}" ... />
...
</Window>
This is just a quick example and you can look into the ObjectDataProvider to see if it's right in your scenario. Here is a great resource which shows additional possibilities such as passing parameters to a method etc., via bindings.
You may be able to accomplish this by using
some evil tricks
an IValueConverter
an attached property
a behavior
by creating a read only proxy property.
However I'll would recommend using a property. It's the way WPF is supposed to work and handles all UI updating logic for you, too.
Why do you want to bind to a method?
If I right understand what you want, it should be enough to you to implement IValueConverter interface and assign it in XAML to you columns data binding's Converter attribute: here is an example how to use it: WPF Converter Example
for more detailed analysis can have a look on SvnRadar opensource project that use a bunch of them.
EDIT
There is no DataGrid control actually, there is a ListView, but the consept is the same.
Hope this helps.

Is there an MVVM-friendly way to swap views without value converters firing unnecessarily?

I thought what I was doing was right out of the Josh Smith MVVM handbook, but I seem to be having a lot of problems with value converters firing when no data in the view-model has changed.
So, I have a ContentControl defined in XAML like this:
<ContentControl Grid.Row="0" Content="{Binding CurrentViewModel}" />
The Window containing this ContentControl references a resource dictionary that looks something like this:
<ResourceDictionary ...>
<DataTemplate DataType="{x:Type lib_vm:SetupPanelViewModel}">
<lib_v:SetupPanel />
</DataTemplate>
<DataTemplate DataType="{x:Type lib_vm:InstructionsPanelViewModel}">
<lib_v:InstructionsPanel />
</DataTemplate>
</ResourceDictionary>
So, basically, the two data templates specify which view to show with which view-model.
This switches the views as expected whenever the CurrentViewModel property on my window's view-model changes, but it also seems to cause value converters on the views to fire even when no data has changed. It's a particular problem with IMultiValueConverter classes, because the values in the value array get set to DependencyProperty.UnsetValue, which causes exceptions unless I specifically check for that. But I'm getting other weird side effects too.
This has me wondering if I shouldn't just do everything manually, like this:
Instantiate each view.
Set the DataContext of each view to the appropriate view-model.
Give the ContentControl a name and make it public.
Handle the PropertyChanged event for the window.
In the event handler, manually set the Content property of the ContentControl to the appropriate view, based the CurrentViewModel (using if statements).
This seems to work, but it also seems very inelegant. I'm hoping there's a better way.
Could you please advise me the best way to handle view switching so that value converters don't fire unnecessarily?
You should look at PRISM or any other composite UI framework. Prism will give you a great mechanism for this type of thing.
I solved this by getting rid of all IValueConverter and IMultiValueConverter classes and just using the ViewModel to provide all data. It turns out, this requires less code and hassle, and doesn't sacrifice anything that I'm aware of.

Categories