Hello all I have the following data template:
<DataTemplate DataType="Integer">
<StackPanel>
<xctk:IntegerUpDown Minimum="{Binding XPath=Min}"
Maximum="{Binding XPath=Max}"
Increment="{Binding XPath=Inc}"
ClipValueToMinMax="True"
AllowSpin="True">
<xctk:IntegerUpDown.Resources>
<converters:Parameter x:Key="IntegerParameter"
CurrentDevice="{Binding ElementName=Dock, Path=DataContext.CurrentDevice}"
ParameterName="{Binding RelativeSource={RelativeSource TemplatedParent}, XPath=#RegisterName}"
ParameterType="Integer">
</converters:Parameter>
</xctk:IntegerUpDown.Resources>
<xctk:IntegerUpDown.Value>
<Binding XPath="#Name"
Converter="{StaticResource IntegerDataConverter}"
ConverterParameter="{StaticResource IntegerParameter}"
Mode="TwoWay"/>
</xctk:IntegerUpDown.Value>
</xctk:IntegerUpDown>
</StackPanel>
</DataTemplate>
Aim of this data template is to call the converter to set the value of the IntegerUpDown control reading it from an external device.
Details on how to contact the device are stored in the converters:Parameter class (derived from dependency object). Two way means that the same mechanism should be used with ConvertBack to write the value to the device.
MultiBinding is not an option since the ConvertBack method could not be used to "create" all the parameters from a single integer value.
This template works almost as intended: I get an instance of the Parameter class for each item the data template is applied to.
Unfortunately the values for CurrentDevice (that should bind to the DataContext property CurrentDevice of the window named "Dock") and ParameterName (that should bind to an Xml attribute of the Xml Node the DataTemplate is applied to) are always null.
I'm sure the issue is in the way I try to bind the Parameter properties, but I'm not able to figure out the correct syntax. Any idea on how to get the result (I can't believe this can't be done... ).
Thanks for any help you can provide
As you may guess my idea was trying to find a workaround for the "you can't bind ConverterParameter" issue.
After further research on internet I found this post:
Bindable Converter Parameter
from this ntg123 guy. It actually solves my problem allowing to somehow bind the ConverterParameter to multiple sources using a syntax almost identical to the standard one.
It is based on a custom MarkupExtension and works really well in situations where Multibinding is not possible.
Related
Okay so in wpf xaml markup the data binding features allow for data binding a list to a listView. To do I specified the DataContext and set the ItemSource to the DataContext. This works and the listView is populated with the items. The items though are objects and to be able to have the displayed item in the list view as a string property of get set implementation from the object enumerated in the list view I am attempting to use an Item Template. Though this is not working and I'm uncertain why.
How exactly does Item Template and the Data Binding function in this scenario? And what would be workable solutions to this problem? Is there a way to specify the property in the text box as being local to the enumerated objects. Please Help I've honestly been working on this for a while and research hasn't provided the answers.
ItemList is a list of objects. ItemName is a string property of ItemList. The ItemSource and DataContext works but the textblock does not.
Preferably a solution using only xaml.
<ListView DataContext="this.ItemList" ItemsSource="{Binding }" Name ="Items">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ItemName}" >
</TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
Except for some unconventional ways of working pointed out by Clemens, I think the only actual error you make is the fact that ItemName is a property of ItemList instead of the enumerated objects' class.
You ask "Is there a way to specify the property in the text box as being local to the enumerated objects". Well, this is the actual case: the TextBlock's datacontext IS the enumerated object. More precisely: all bindings in the itemtemplate will go look in the enumerated object unless the binding explicitly tells otherwise. So, if your enumerated object has eg. a string property ObjectName, its value will definitely get bound and shown by the textblock.
I'm learning WPF and MVVM. I'm curious about what happens in a particular situation.
Assuming that my view model implements INotifyPropertyChanged, the situation is where my code has already constructed my view model and then assigns it to my window's DataContext.
At the point in time that I assign the view model to DataContext, the value in my view model may be different than the value in the XAML element. And so I'm curious about which value wins.
I assumed the XAML element would pull in all the values from my view model but that is not what seems to be happening. Changes made to my view model correctly notify and update the XAML elements. But those changes made before I set DataContext are not reflected in the XAML elements.
Can anyone confirm my interpretation is correct? I've Googled extensively but could not find anything on this specific issue. Yet that seems to be the behavior in my application. Would appreciate someone else perspective or a link to a more detailed discussion.
I'm curious about the situation where my view model implements INotifyPropertyChanged, my code builds my view model and then assign it to my windows DataContext.
The problem is, at that stage where I assign to DataContext, the value in the XAML element may not match my view model. So which one wins.
Based on my testing, it appears that the value already in the XAML element wins. And if I want it set to the value in my view model, I must set it somehow or have my view model send a new property-changed notification.
Sounds like your changing your data template to show a hardcoded value rather than the default value provided by the binding.
For example in a TextBlock you can only assign the Text property once, either via a binding syntax where the value is sourced from the DataContext, or a static value.
<TextBlock Text="{Binding Path=Display}"/> <- only uses the DataContext
<TextBlock Text="123"/> <- only shows the static value
If you try and set the Text property twice, you get an error:
<TextBlock Text="{Binding Path=Display}">
<TextBlock.Text>
123
</TextBlock.Text>
</TextBlock>
You can provide the binding with a fallback value when there is no valid value available via the DataContext such as an exception being thrown, but the DataContext value wins when it provides a value:
<TextBlock Text="{Binding Path=Display, FallbackValue=123}" />
If you want to set a default value, you might be best to set a default in the constructor of the DataContext class and leave the binding in the Xaml to only source from the DataContext
In MainWindow we have:
<HeaderedContentControl
Content="{Binding Path=Workspaces}"
ContentTemplate="{StaticResource WorkspacesTemplate}"
Header="Workspaces"
Style="{StaticResource MainHCCStyle}"
/>
In the resources:
<DataTemplate x:Key="WorkspacesTemplate">
<TabControl
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding}"
ItemTemplate="{StaticResource ClosableTabItemTemplate}"
Margin="4"
/>
</DataTemplate>
And in the article says:
A typed DataTemplate does not have an x:Key value assigned to it, but
it does have its DataType property set to an instance of the Type
class. If WPF tries to render one of your ViewModel objects, it will
check to see if the resource system has a typed DataTemplate in scope
whose DataType is the same as (or a base class of) the type of your
ViewModel object. If it finds one, it uses that template to render the
ViewModel object referenced by the tab item's Content property.
My question is:
How does the template know that the type is a collection of workspaces (WorkspaceViewModel)?
It doesn't need to, in the code you've posted. In your sample, you have given a strict value to your content template: you've explicitly used {StaticResource WorkspacesTemplate}, and so a resource with the key of "WorkspacesTemplate is looked up.
Because you've explicitly set the template, it doesn't matter what the intended type is: it'll try to display any object in your Content using the template you've set - with varying degrees of success if you use a type that doesn't match!
In the alternate method you mention - with a "typed DataTemplate", you would declare your datatemplate with <DataTemplate DataType="{x:Type l:WorkSpace}" />. Note that there is no x:Key (and also that I've assumed you have a namespace l mapped to your local code). What happens here is that WPF automatically sets the key of your resource to the DataType (important to note: a resource key doesn't have to be a string!).
Then, when you declare your HeaderedContentControl, you can leave out setting the ContentTemplate. At runtime, when the control is rendered, WPF will check the type of the Content object and find that it is WorkSpace, and it'll then look up a resource with x:Key="{x:Type l:WorkSpace}" - which will match your typed template.
This is a useful way of making consistent representations of data throughout your application, since a typed DataTemplate will be used automatically by any content-presenting control throughout your application.
WPF doesn't really care about the concrete type, it's just need to be some IEnumerable of something, WPF uses the type descriptor to know what the ui binding with.
I'm utilizing a data grid which has three columns of type DataGridTemplateColumn. These columns share almost identical behaviors and, as a consequence, utilize almost identical templates. The templates are copy-paste with a few resources changed out.
I would like to refactor the templates in to a generic version which uses an attached property to provide the necessary data. I've tried this but have been unable to access the property from inside the CellTemplate.
Methods I've tried are:
Bindings using RelativeSource: TemplatedParent.
Bindings using RelativeSource with various AncestorTypes.
Adding FrameworkPropertyMetadataOptions.Inherits to the FrameworkPropertyMetadata of the attached property.
The CellTemplate seems to have an odd degree of separation from its surroundings. What am I missing. If nothing, what is the appropriate solution to this problem?
A code example from you would have been helpful, but assuming that you have attached your property to the DataGrid, you should be able to bind to it from the CellTemplate using the following (untested):
<TextBlock Text="{Binding Path=(YourNamespace:YourClassName.YourAttachedPropertyName),
RelativeSource={RelativeSource AncestorType=DataGrid}, FallbackValue=''}" />
If you attached the property to the DataGridTemplateColumn, you would use:
<TextBlock Text="{Binding Path=(YourNamespace:YourClassName.YourAttachedPropertyName),
RelativeSource={RelativeSource AncestorType=DataGridTemplateColumn}, FallbackValue=''}" />
The FallbackValue property is not required, but it's a good practice to use it to avoid binding errors if the binding source can't be found.
Can't seem to figure this out and I thought It would be easy.
I have a WCF service that returns an observablecollection
I want to call the wcf service from code behind and place the results into a observablecollection _myObser. I need this _myObser accessible from my XAML..
<sdk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox x:Name="cbGroup" SelectedItem="{Binding Group, Mode=TwoWay}"
ItemsSource="??" />
</DataTemplate>
</sdk:DataGridTemplateColumn.CellEditingTemplate>
I guess my first question is there a better way to do this?
My second question am I able to do something like this? I seem to always get errors
<navigation:Page.Resources>
<observablecollection<customtype> x:name""....
I also tried to use my wcfservicereference return arguments as a resource but I get this error.
xmlns:STA="clr-namespace:ePagesSilverlightWebsite.ePagesWCFServiceReference"
<navigation:Page.Resources>
<STA:getAccessLevelsCompletedEventArgs x:Name="_myOb" />
</navigation:Page.Resources>
is not usable as an object element because it is not public or does not define a public parameterless constructor or a type converter
Set the DataContext of the page to either the code behind (this) or a view model, define the Observable collection as a readonly public property in the code behind or the view model and bind to the property.