I'm trying to bind a decimal value (SalePrice) from my database to the MaxInclusive property of a ValueConstraint like this:
<Label Margin="0,0,4,0" Content="{Binding Path=SalePrice}"/><igEditors:XamNumericEditor x:Name="xnumAmountSaleRefunded"> <igEditors:XamNumericEditor.ValueConstraint> <igEditors:ValueConstraint ValidateAsType="Decimal" MinInclusive="0" MaxInclusive="{Binding Path=SalePrice, Mode=OneWay}" /> </igEditors:XamNumericEditor.ValueConstraint></igEditors:XamNumericEditor>
I added a lable just above the XamNumericEditor just to verify that the binding to SalePrice works, and it does. It shows a value of 24.95 when run.
The SalePrice field in the SQL database is defined as Decimal(10,2).
The problem is that the constraint just doesn't seem to do anything. I can enter any max value and it doesn't catch it.
If I change it to say MaxInclusive="24.95", of course it works. I've tried it with and without the Mode=OneWay, and I've also tried changing the ValidateAsType to Float, Double, Unknown, even Integer64 and a few others and nothing seems to work.
What am I doing wrong?
Hi, I am evaluating the Infragistics WPF controls, I seem to have the same problem:
<igEditors:XamNumericEditor
Value=
"{Binding Path=ValueMine, diag:PresentationTraceSources.TraceLevel=High, ElementName=MyNumEdit, Mode=TwoWay}"
x:Name="MySpinner"
HorizontalAlignment="Left"
Margin="10,42,0,0"
Mask="{}{double:6.2}"
PromptChar=" "
SpinButtonDisplayMode="Always"
SpinIncrement="0.5"
ValueType="{x:Type my:Double}"
VerticalAlignment="Top" Width="138">
<igEditors:XamNumericEditor.ValueConstraint>
<igEditors:ValueConstraint
MaxInclusive=
"{Binding Path=ValueMaxMine, diag:PresentationTraceSources.TraceLevel=High, ElementName=MyNumEdit, Mode=TwoWay }"
MinInclusive=
"{Binding Path=ValueMinMine, diag:PresentationTraceSources.TraceLevel=High, ElementName=MyNumEdit, Mode=TwoWay}"
/>
</igEditors:XamNumericEditor.ValueConstraint>
</igEditors:XamNumericEditor>
Looking at the output window :
...
System.Windows.Data Warning: 65 : BindingExpression (hash=50340407): Resolving source (last chance)
System.Windows.Data Warning: 67 : BindingExpression (hash=50340407): Framework mentor not found
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=ValueMaxMine; DataItem=null; target element is 'ValueConstraint' (HashCode=50690790); target property is 'MaxInclusive' (type 'Object')
System.Windows.Data Warning: 65 : BindingExpression (hash=50070782): Resolving source (last chance)
System.Windows.Data Warning: 67 : BindingExpression (hash=50070782): Framework mentor not found
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=ValueMinMine; DataItem=null; target element is 'ValueConstraint' (HashCode=50690790); target property is 'MinInclusive' (type 'Object')
ElementName bindings would only work for properties of objects in the visual tree (i.e. uielements). The ValueConstraint is a subobject that contains constraint related properties but it is not a visual element so you cannot do element name bindings on its properties. This works for the Value property because that is a property of the visual element (the xamNumericEditor in this case). If you wanted you could probably create your own IValueConverter that would create a ValueConstraint. e.g.
public class ValuesToValueConstraintConverter : IMultiValueConverter { object IMultiValueConverter.Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (values == null || values.Length != 2) return Binding.DoNothing; ValueConstraint vc = new ValueConstraint(); vc.MinInclusive = values[0]; vc.MaxInclusive = values[1]; return vc; } object[] IMultiValueConverter.ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) { return new object[] { Binding.DoNothing }; } }
ValueConstraint vc = new ValueConstraint(); vc.MinInclusive = values[0]; vc.MaxInclusive = values[1];
return vc; }
object[] IMultiValueConverter.ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) { return new object[] { Binding.DoNothing }; } }
Then you would use it like this:
<StackPanel xmlns:local="clr-namespace:WpfApplication3"> <StackPanel.Resources> <local:ValuesToValueConstraintConverter x:Key="valueConstraintConverter" /> </StackPanel.Resources> <igEditors:XamNumericEditor x:Name="numMin" Value="0" SpinButtonDisplayMode="Always" /> <igEditors:XamNumericEditor x:Name="numMax" Value="20" SpinButtonDisplayMode="Always" /> <igEditors:XamNumericEditor> <igEditors:XamNumericEditor.ValueConstraint> <MultiBinding Converter="{StaticResource valueConstraintConverter}"> <Binding ElementName="numMin" Path="Value" /> <Binding ElementName="numMax" Path="Value" /> </MultiBinding> </igEditors:XamNumericEditor.ValueConstraint> </igEditors:XamNumericEditor> </StackPanel>
Thanks for the fast answer! very impressive :)
hans
Hi again,
Andrew, I tried your solution and it solves part of my problem. In a situation where I use the control directly in a window it works fine now and the errors are gone, thanks!.
However when I make a usercontrol and set some dependencyproperties to my max/min values the control ends up having no range at all and the only valid value is the max or min value that is last in the xaml.
here is the code from the usercontrol setting the depprops
public static readonly DependencyProperty MinValProperty =
DependencyProperty.Register("ValueMinMine", typeof(double), typeof(UserControl1));
public double ValueMinMine
{
get
return (double)GetValue(UserControl1.MinValProperty);
}
set
SetValue(UserControl1.MinValProperty, value);
public static readonly DependencyProperty MaxValProperty =
DependencyProperty.Register("ValueMaxMine", typeof(double), typeof(UserControl1));
public double ValueMaxMine
return (double)GetValue(UserControl1.MaxValProperty);
SetValue(UserControl1.MaxValProperty, value);
public class ValuesToValueConstraintConverter : IMultiValueConverter
object IMultiValueConverter.Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
if (values == null || values.Length != 2)
return Binding.DoNothing;
ValueConstraint vc = new ValueConstraint();
vc.MinInclusive = values[0];
vc.MaxInclusive = values[1];
return vc;
object[] IMultiValueConverter.ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
return new object[] { Binding.DoNothing };
and the xaml from the usercontrol
<igEditors:XamNumericEditor Value="{Binding Path=ValueMine,diag:PresentationTraceSources.TraceLevel=High, ElementName=MyNumEdit, Mode=TwoWay}"
SpinIncrement="1"
<MultiBinding Converter="{StaticResource valueConstraintConverter}">
<Binding ElementName="MyNumEdit" Path="ValueMaxMine" Mode="OneTime" diag:PresentationTraceSources.TraceLevel="High" />
<Binding ElementName="MyNumEdit" Path="ValueMinMine" Mode="OneTime" diag:PresentationTraceSources.TraceLevel="High"/>
</MultiBinding>
Am I missing something here?
Thanks
Hans
The order of the bindings in the multi binding must match up with how the converter is expecting them.
hansrwindhoff said: ValueConstraint vc = new ValueConstraint(); vc.MinInclusive = values[0]; vc.MaxInclusive = values[1];
hansrwindhoff said: <MultiBinding Converter="{StaticResource valueConstraintConverter}"> <Binding ElementName="MyNumEdit" Path="ValueMaxMine" Mode="OneTime" diag:PresentationTraceSources.TraceLevel="High" /> <Binding ElementName="MyNumEdit" Path="ValueMinMine" Mode="OneTime" diag:PresentationTraceSources.TraceLevel="High"/> </MultiBinding>
The converter expects the first to be the MinInclusive and the second to be the MaxInclusive but you are passing the ValueMax as the 1st parameter and ValueMin as the 2nd parameter.
Hi Andrew, thanks for your answer. I only mentioned the sequence because I thought it would give some clue. That was just an observation.
The main problem is that I cant bind the max /min values when using the XamNumericEditor in a usercontrol. For the XamNumericSlider the binding of the max/min value work just as expected even if used within the user control.
When using the XamNumericEditor directly from a window the bindung method you proposed works good.
However I think it would be useful to put XamNumericEditor into a usercontrol together with XamNumericSlider and to be able to set the max/min values for each instance of the usercontrol differently. Thinking about it I also would need the SpinIncrement to be bound.
Here is some simplified code. It creates a window with my user control, unfortunately the XamNumericEditor has an invalid range. Its still the range (4...82) from the underlying component not the range that was bound from the container. The slider has the correct range (110...1100).
My container window looks like this:
<Window x:Class="t1wpf.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="Window_2"
Title="Window2" Height="288" Width="571"
xmlns:my1="clr-namespace:t1wpf"
xmlns:ig="http://schemas.infragistics.com/xaml"
xmlns:igEditors="http://infragistics.com/Editors" xmlns:igCA="http://infragistics.com/Chart"
xmlns:my="clr-namespace:Infragistics.Samples.WPF.xamFeatureBrowser.XamChart"
xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
<Grid>
<my1:UserControl1 x:Name="userControl11"
ValueMine="{Binding ElementName=Window_2, Path=mynum}"
ValueMaxMine="{Binding ElementName=Window_2, Path=mynumMax, Mode=TwoWay}"
ValueMinMine="{Binding ElementName=Window_2, Path=mynumMin, Mode=TwoWay}"
HorizontalAlignment="Left" Margin="12,49,0,0" VerticalAlignment="Top">
</my1:UserControl1>
</Grid>
</Window>
The code behind is :
namespace t1wpf
/// <summary>
/// Interaction logic for Window2.xaml
/// </summary>
public partial class Window2 : Window
public Window2()
mynum = 142;
mynumMax = 1100;
mynumMin = 110;
InitializeComponent();
private double _mynum;
public double mynum
get { return _mynum; }
_mynum = value;
Debug.WriteLine(value);
private double _mynumMax;
public double mynumMax
get { return _mynumMax; }
_mynumMax = value;
private double _mynumMin;
public double mynumMin
get { return _mynumMin; }
_mynumMin = value;
<UserControl x:Class="t1wpf.UserControl1"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="135"
d:DesignWidth="343"
xmlns:igEditors="http://infragistics.com/Editors"
xmlns:my="clr-namespace:System;assembly=mscorlib"
xmlns:t1wpf="clr-namespace:t1wpf"
x:Name="MyNumEdit"
xmlns:my1="clr-namespace:NumericBox;assembly=NumericBox"
xmlns:local="clr-namespace:t1wpf"
>
<UserControl.Resources>
<local:ValuesToValueConstraintConverter x:Key="valueConstraintConverter" />
</UserControl.Resources>
<Canvas Height="136" Name="canvas1" Width="339" >
<ig:XamNumericSlider x:Name="MySlider"
Value="{Binding Path=ValueMine, diag:PresentationTraceSources.TraceLevel=High, ElementName=MyNumEdit, Mode=TwoWay}"
MinValue="{Binding Path=ValueMinMine, diag:PresentationTraceSources.TraceLevel=High, ElementName=MyNumEdit, Mode=TwoWay}"
MaxValue="{Binding Path=ValueMaxMine, diag:PresentationTraceSources.TraceLevel=High, ElementName=MyNumEdit, Mode=TwoWay}"
Margin="169,44,0,0"
VerticalAlignment="Top"
Width="159" Grid.ColumnSpan="2" />
<!--<igEditors:XamNumericEditor.ValueConstraint>
MaxInclusive="{Binding Path=DataContext.ValueMaxMine, diag:PresentationTraceSources.TraceLevel=High, ElementName=MyNumEdit, Mode=TwoWay }"
MinInclusive="{Binding Path=DataContext.ValueMinMine, diag:PresentationTraceSources.TraceLevel=High, ElementName=MyNumEdit, Mode=TwoWay}"
</igEditors:XamNumericEditor.ValueConstraint>-->
<Label Content="Label" Height="28" HorizontalAlignment="Left" Margin="10,10,0,0" Name="label1"
VerticalAlignment="Top" Width="318" Grid.ColumnSpan="2" />
<!--<Slider Name="sldr"
Value="{Binding Path=ValueMine, ElementName=MyNumEdit, Mode=TwoWay}"
Maximum="{Binding Path=ValueMaxMine, ElementName=MyNumEdit, Mode=TwoWay}"
Minimum="{Binding Path=ValueMinMine, ElementName=MyNumEdit, Mode=TwoWay}"
Margin="31,101,26,0" Height="31" VerticalAlignment="Top" Width="316" Canvas.Left="-19" />-->
<Label Content="{Binding Path=ValueMine, ElementName=MyNumEdit, Mode=TwoWay}" Margin="10,69,12,58" Height="27" Width="318" />
</Canvas>
</UserControl>
and the code behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Infragistics.Windows.Editors;
public partial class UserControl1 : System.Windows.Controls.UserControl
public UserControl1()
ValueMine = 12;
ValueMinMine = 4;
ValueMaxMine = 82;
//base.DataContext = this;
DataContext = this;
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("ValueMine", typeof(double), typeof(UserControl1));
public double ValueMine
return (double)GetValue(UserControl1.ValueProperty);
SetValue(UserControl1.ValueProperty, value);
vc.MinInclusive = values[1];
vc.MaxInclusive = values[0];
thanks for your patience
Unless I'm missing something the problem is that you are using a OneTime binding on the bindings in the multi value converter. It works for the slider because you have a TwoWay binding there so when the property is changed (because you bound it to the property on the window) the slider gets the newer value but since the value constraint has a OneTime binding it only gets the initial value. I think that you want OneWay bindings on the converter.
Mode="OneWay" works also ;)
That was the reason! Cool, here is the final version that now works:
<Binding ElementName="MyNumEdit" Path="ValueMaxMine" />
<Binding ElementName="MyNumEdit" Path="ValueMinMine" />
Removing the Mode altogether has the same effect as using the Mode="TwoWay".
Thanks for all the help