ComboBox validation error - why does it fail? - wpf

The idea is simple: to select a period in seconds from a RibbonComboBox and save that to an app instance property. The underlying data is in milliseconds but the combo displays them in seconds.
The property in my app stores the time in millis:
private int _updatePeriod;
public int UpdatePeriod
{
get { return _updatePeriod; }
set
{
_updatePeriod = value;
InvokePropertyChanged(new PropertyChangedEventArgs("UpdatePeriod"));
}
}
in XAML i define a list of possible choices, in millis like this:
<x:Array x:Key="UpdateFrequenciesCollection" Type="{x:Type System:Int32}" >
<System:Int32 >100</System:Int32>
<System:Int32 >200</System:Int32>
<System:Int32 >500</System:Int32>
<System:Int32 >1000</System:Int32>
<System:Int32 >2000</System:Int32>
</x:Array >
I then have a ribbon toolbar combo box setup like this:
<ribbon:RibbonComboBox IsEditable="False" AllowDrop="False" Grid.Column="1" Grid.Row="1" IsDropDownOpen="False">
<ribbon:RibbonGallery x:Name="RibbonGalleryUpdatePeriod" SelectedValue="{Binding Path=UpdatePeriod, Mode=TwoWay, Source={x:Static Application.Current}}">
<ribbon:RibbonGalleryCategory x:Name="RibbonGalleryCategoryUpdatePeriod" ItemTemplate="{StaticResource UpdatePeriodTemplate}" ItemsSource="{Binding Source={StaticResource UpdateFrequenciesCollection}}">
</ribbon:RibbonGalleryCategory>
</ribbon:RibbonGallery>
</ribbon:RibbonComboBox>
This is the simple template for the combo box item:
<DataTemplate x:Key="UpdatePeriodTemplate">
<StackPanel Orientation="Horizontal" >
<TextBlock Text="{Binding Converter={StaticResource DivideConverter}, ConverterParameter=1000, StringFormat={}{0:0.0 s}}"/>
</StackPanel>
</DataTemplate>
Functionally its okay, as in it sets and get the correct value in the combobox<->UpdatePeriod. However the dropdown always has a red border which I think indicates an a validation error. Any idea what can cause this, or how I can debug the error in some way?? Much appreciated!

If your Binding has associated validation rules but you do not specify an ErrorTemplate on the bound control, a default ErrorTemplate will be used to notify users when there is a validation error. The default ErrorTemplate is a control template that defines a red border in the adorner layer.
I guess RibbonComboBox does define a validation rule.
You can set the attached property PresentationTraceSources.TraceLevel and see the binding error but I would start with Snoop

Related

WPF: UserControl not displaying at design time inside Datatemplate for a ContentControl

I spent quite some days trying to figure out what is not working here, and I suspect it is eighter a bug in VS or something plain simple I oversee...
I have a ContentControl which serves a view model:
<!-- Learning control from DataTemplate -->
<ContentControl Content = "{Binding learningViewModel}"
Grid.Row = "1"
Grid.Column = "1"
Height = "300"
Margin = "20, 0, 0, 0"/>
The property it is bound to is actually an interface to a set of view models.
Then I have a definition of DataTemplate for the possible ViewModels:
<Window.Resources>
<DataTemplate DataType="{x:Type vm:vmLearnSpeak}">
<local:viewLearnSpeak CommandNotKnown = "{Binding DataContext.cmdNotKnown, RelativeSource={RelativeSource AncestorType=local:wndSession}}"
CommandAlmostKnown = "{Binding DataContext.cmdAlmostKnown, RelativeSource={RelativeSource AncestorType=local:wndSession}}"
CommandKnown = "{Binding DataContext.cmdKnown, RelativeSource={RelativeSource AncestorType=local:wndSession}}" />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:vmLearnWrite}">
<local:viewLearnWrite CommandNotKnown = "{Binding DataContext.cmdNotKnown, RelativeSource={RelativeSource AncestorType=local:wndSession}}"
CommandAlmostKnown = "{Binding DataContext.cmdAlmostKnown, RelativeSource={RelativeSource AncestorType=local:wndSession}}"
CommandKnown = "{Binding DataContext.cmdKnown, RelativeSource={RelativeSource AncestorType=local:wndSession}}" />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:vmLearnListen}">
<local:viewLearnListen CommandNotKnown = "{Binding DataContext.cmdNotKnown, RelativeSource={RelativeSource AncestorType=local:wndSession}}"
CommandAlmostKnown = "{Binding DataContext.cmdAlmostKnown, RelativeSource={RelativeSource AncestorType=local:wndSession}}"
CommandKnown = "{Binding DataContext.cmdKnown, RelativeSource={RelativeSource AncestorType=local:wndSession}}" />
</DataTemplate>
</Window.Resources>
During programm execution the binding works as expected.
However during design time the ContentControl will only display a plain string representing the path of the view model (eg. "MyApp.ViewModels.vmLearnSpeak").
All view models have default constructors which initialize some dummy data and if I change that dummy initialization in the ViewModel that has the property the ContentControl is bound to, then the DataTemplate is also changed in designer as expected (the string changes to "MyApp.ViewModels.vmLearnWrite" for example).
If I replace the DataTemplate content by another control like a button, I get the button displayed if the correcponding Data for the DataTemplate with the button is set.
So in all, DataTemplate is basically working.
The custom controls work too: if I put the code from the DataTemplate directly in the layout, then the control appears as expected.
Hence it appears that the control will only fail to display during design time if placed inside a DataTemplate...
I hope I provided enough information, else let me know... Thanking you in advance for your support!
BTW: running Visual Studio 2016 communities, just in case there might be a known bug (After spending so much time trying to fix I am not sure but I believe that it used to work some time ago...)
EDIT:
The issue really is with the UserControl, if I add a simple empty or with only a button UserControl the same issue is there. Hoewver if i put a CustomControl or a regular Button, the DataTemplate is shown...
Just for information: apparently this was a bug in Visual studio that has been fixed, while I am not sure when it will release:
https://developercommunity.visualstudio.com/content/problem/1004742/usercontrol-is-not-displayed-inside-datatemplate-i.html

Creating a checkbox in a Xceed Datagrid in WPF

I have an application that uses the Xceed DataGrid for WPF. In it I have a column that has a checkbox and I would like the IsChecked or Checked event to call a function. Problem is with everything I've done I either get a running application that does nothing except toggle the check box or I get the following exception thrown:
Failed to create a 'Checked' from the text 'CheckBoxChecked'
All I would like to do is to somehow bind the checkbox to call a function when the user toggles it. I am still a bit new to the WPF binding framework. I have added the small snippet of code that I am using when creating the DataTemplate in regards to this column:
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Checked="CheckBoxChecked" />
</StackPanel>
</DataTemplate>
Thanks in advance for any help.
May I suggest you a more WPF-correct approach? You bind the checkbox to a property then react when this property is changed:
XAML:
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsSomething}" />
</StackPanel>
</DataTemplate>
In the class of your DataContext:
private bool isSomething;
public bool IsSomething
{
get { return isSomething; }
set
{
isSomething = value;
DoSomething();
}
}

How to set TextSearch.Text for a combobox whose TextBlock uses converter?

In the below code, Combobox is wired to NameInfo object along with a converter.NameInfoConverter returns a format in which items in combobox are shown in a particular format (for eg: LastName, FirstName (Badge#) )
Now, when I set TextSearch.Text="{Binding NameInfo, Converter={StaticResource NameInfoConverter}, ConverterParameter=true}" on combobox; TextSearch doesn't work. When I set TextSearch.TextPath="Name", search itself works but doesnot get the correct format displayed in the selectionbox of combobox.
Any Ideas?
<StackPanel>
<ComboBox x:Name:"cmbName">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name,
Converter={StaticResource NameInfoConverter}, ConverterParameter=true}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
You've probably hit a limitation in the API. I suggest you take an alternative route and bind directly to a property that is correctly formatted for your textblock.
If this is a serious app, you may want to look into using the MVVM pattern and place your converted/formatted property in the viewmodel. Otherwise, just create a new property on your databound class called NameInfo or something and do the conversion from that.

Silverlight Gridcolumn Collapse Visibility in code

I'm having a small problem.
I have this grid with a column:
<data:DataGrid ColumnHeaderStyle="{StaticResource headerStyle}" Foreground="#234BC3" AutoGenerateColumns="False" Name="protocollenBAMDataGrid" LoadingRow="myDataGrid_LoadingRow" SelectionChanged="DataGrid_SelectionChanged">
<data:DataGrid.Columns>
<data:DataGridTemplateColumn Header="Resend" x:Name="ResendColumn">
<data:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="Resend" Tag="{Binding MsgID}" Foreground="#234BC3" Click="dataGridHL7_Click"></Button>
</DataTemplate>
</data:DataGridTemplateColumn.CellTemplate>
</data:DataGridTemplateColumn> ...
If i set the visibility of the "ResendColumn" to collapsed, it works fine.
However I need to do this in code, so I tried doing this in the loading event:
ResendColumn.Visibility = Visibility.Collapsed;
And it gives me a nullref exception:
Object reference not set to an
instance of an object.
I don't understand why?
I get the same behaviour in SL 4. I guess it is related to the column not being a UIElement and thus instantiated by the DataGrid itself (not by the usual stuff happening in InitializeComponent).
I had to access the columns through the Columns property of the DataGrid. And there, setting the visibility works.

WPF: Collection dependency property "is read-only and cannot be set from markup"

I am creating a user control to display a three-month calendar. The control is based on the WPF Calendar control (WPF Toolkit 2009-06), and I want to pass several of the Calendar's properties through to corresponding properties of my user control. The user control properties are set up as Dependency Properties, and their underlying types match the types of the Calendar properties. Here is my markup:
<StackPanel>
<toolkit:Calendar Name="MasterCalendar"
SelectionMode="{Binding Path=SelectionMode, Mode=OneWay}"
SelectedDate="{Binding Path=SelectedDate, Mode=OneWayToSource}"
SelectedDates="{Binding Path=SelectedDates, Mode=OneWayToSource}"/>
<toolkit:Calendar Name="SlaveCalendar1"
DisplayDate="{Binding DisplayDate, Converter={StaticResource IncrementalMonthConverter}, ElementName=MasterCalendar, Mode=OneWay}"
SelectionMode="{Binding Path=SelectionMode, Mode=OneWay}"
SelectedDate="{Binding Path=SelectedDate, Mode=OneWayToSource}"
SelectedDates="{Binding Path=SelectedDates, Mode=OneWayToSource}"/>
<toolkit:Calendar Name="SlaveCalendar2"
DisplayDate="{Binding DisplayDate, Converter={StaticResource IncrementalMonthConverter}, ElementName=SlaveCalendar1, Mode=OneWay}"
SelectionMode="{Binding Path=SelectionMode, Mode=OneWay}"
SelectedDate="{Binding Path=SelectedDate, Mode=OneWayToSource}"
SelectedDates="{Binding Path=SelectedDates, Mode=OneWayToSource}"/>
</StackPanel>
All of the properties bind without problem, except for the SelectedDates property. I get the following error on its binding:
'SelectedDates' property is read-only and cannot be set from markup.
I suspect that it is because the SelectedDates property is a collection, but I am not sure how to fix the problem. Can anyone enlighten me on the cause of the problem and suggest a fix? Thanks for your help.
If I understand you well, you have Dependency properties in your code behind that match in name and type the properties of the Calendar Controls in your user control. You are trying to assign the SelectedDates Collection of the various Calendar Controls to the Dependency property of the same name in your code behind.
You can simply do this by a line of code:
this.SelectedDates=SlaveCalendar1.SelectedDates
In an appropriate EventHandler that fires when a selected date is added.
Even though you set the binding to OneWayToSource the SelectedDates= piece of code is an assignment. As the SelectedDates Property has no setter, it is not possible to write this piece of code.
Here you can find a link to the Calendar Control's documentation

Resources