Binding Row to Validation Rule WPF - wpf

I want to bind TextBox's Tag (which is inside a DataGrid), to validation rule's CurrentLegStrategy property (which is a DependencyProperty). Although I've done something similar with Deal dependency property using a global tunnel object, however not able to figure out, what would be the tunnel for CurrentLegStrategy (ideally should be coming from the bound data to DataRow or to the bound data to TextBox's tag)?
<DataTemplate x:Key="PremiumProp">
<TextBlock Style="{StaticResource TextBlockLeft}" Tag="{Binding Strategy}" x:Name="txtPremiumProp">
<TextBlock.Text>
<Binding Path="AbsolutePremium" StringFormat="{}{0:#,##0.00####}" Converter="{StaticResource _DoubleConvertor}">
<Binding.ValidationRules>
<Control:MBSStrategyBasedDoubleValidation ValidatesOnTargetUpdated="True" ValidationTag="premabs"
ErrorMessage="Please enter a valid positive (+) premium (also check the reference which is required for auto calculation)!">
<Control:MBSStrategyBasedDoubleValidation.Deal>
<Control:DealObject Deal="{Binding Tag, Source={StaticResource TradeTunnel}}" CurrentLegStrategy="{Binding Path=Tag, ElementName=txtPremiumProp}"/>
</Control:MBSStrategyBasedDoubleValidation.Deal>
</Control:MBSStrategyBasedDoubleValidation>
</Binding.ValidationRules>
</Binding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
Then I also tried,
<TextBlock.Resources>
<ResourceDictionary>
<FrameworkElement x:Name="strategySource" Tag="{Binding Tag, Source={x:Reference txtPremiumProp}}"/>
</ResourceDictionary>
</TextBlock.Resources>
With the following:
CurrentLegStrategy="{Binding Path=Tag, Source={StaticResource strategySource}}"
Cannot find resource named 'strategySource'. Resource names are case sensitive.

Related

WPF TextBox control filter + validation

I have TextBox bound to a text property in my window with a validation rule (length is = 4). I needed to add filtering so I took ThomasLebruns WPFDeveloperTools FilteredTextBox. That works but when I use the control I specify each time the Validation.ErrorTemplate and the Binding.ValidationRules - I want to build those into the FilteredTextBox control so they apply automatically to every FilteredTextBox - how to manage that?
Currently I have to:
<Window>
<Grid>
<ps:FilteredTextBox x:Name="textboxPanId" Type="Hex" Grid.Column="1" Grid.Row="1" Height="35" Margin="0,2,0,2" MaxLength="4"
Validation.ErrorTemplate="{StaticResource TextBoxErrorTemplate}">
<TextBox.Text>
<Binding Path="pan_id" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<ps:PanIdValidation />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</ps:FilteredTextBox>
I would like just:
<ps:FilteredTextBox x:Name="textboxPanId" Type="Hex" Grid.Column="1" Grid.Row="1" Height="35" Margin="0,2,0,2" MaxLength="4">
<TextBox.Text>
<Binding Path="pan_id" UpdateSourceTrigger="PropertyChanged"/>
</TextBox.Text>
but have the error template and validation rule applied. How to move the setting of the Validation.ErrorTemplate and Binding.ValidationRule into resource dictionary with rest of FilteredTextBox xaml?.
<ResourceDictionary>
<ControlTemplate x:Key="TextBoxErrorTemplate">
...
</ControlTemplate>
I think if you create a style for FilteredTextBox in your ResourceDictionary you can set these there, but at least the ErrorTemplate for almost sure.

WPF StringFormat databinding text not appearing

I am trying to get the header text of a TreeviewItem to be set in the binding to an XML source. Everything is working fine except the only thing that appears in the header is the text I'm binding to and nothing else in the string format. Example:
<HierarchicalDataTemplate x:Key="LogDataTemp" ItemsSource="{Binding Path=log}">
<TreeViewItem>
<TreeViewItem.Header>
<Binding Path="Attribute[level].Value" StringFormat="TEST \{0\}" />
</TreeViewItem.Header>
</TreeViewItem>
</HierarchicalDataTemplate>
In this case the level value appears but nothing else. I have tried dozens of different ways of approaching this and it seems that nothing works.
Don't escape the braces in the StringFormat. You want to apply the formatting to the 0th-element in your binding.
For instance, with a simple property called "Level":
<TextBlock x:Name="txtUnformatted" Grid.Row="0" Foreground="White" >
<TextBlock.Text>
<Binding Path="Level" />
</TextBlock.Text>
</TextBlock>
<TextBlock x:Name="txtFormatted" Grid.Row="1" Foreground="White">
<TextBlock.Text>
<Binding Path="Level" StringFormat="Test {0:000000}" />
</TextBlock.Text>
</TextBlock>
And the result is something like:
Update
Also, the default implementation of the Header, when you don't add any controls, is a simple ContentPresenter, which doesn't apply formatting. To work around this, simply put a TextBlock into the header, and bind the text you want formatted to that.
<HierarchicalDataTemplate x:Key="LogDataTemp" ItemsSource="{Binding Path=log}">
<TreeViewItem>
<TreeViewItem.Header>
<TextBlock>
<TextBlock.Text>
<Binding Path="Attribute[level].Value"
StringFormat="TEST {0}" />
</TextBlock.Text>
</TextBlock>
</TreeViewItem.Header>
</TreeViewItem>
</HierarchicalDataTemplate>
It is perfectly acceptable (and commonly done) to put controls into a header control (for instance, a grid containing an image and a label). The beauty of WPF.

Bind to several class properties

I have some class with properties firstName and lastName. I want bind TextBlock to concatanation of this two properties. I know that I can create third property that will be return concatanation of these properties. But I dont want to use this approach. Is it possible to Bind TextBlock to two properties. and also I dont want create composite userControl.
In .NET 3.5SP1, Microsoft added StringFormat to bindings. This makes it much easier. See Lester's blog post for an example. In your case:
<TextBox>
<TextBox.Text>
<MultiBinding StringFormat="{0} {1}">
<Binding Path="FirstName" />
<Binding Path="LastName"/>
</MultiBinding>
</TextBox.Text>
</TextBox>
or
<TextBox>
<TextBox.Text>
<MultiBinding StringFormat="{1}, {0}">
<Binding Path="FirstName" />
<Binding Path="LastName"/>
</MultiBinding>
</TextBox.Text>
</TextBox>
You could use multibinding, but I guess that you have to code your way out of the concatanation.
Here is an example: Multibinding
I'm not sure if it's possible to bind to two properties, but there is not reason you cannot create two TextBlocks right?
<TextBlock Text="{Binding firstName}"/> <TextBlock Text="{Binding lastName}"/>
use either MultiBinding or Converter (if complex operation is there)

WPF Commands Buttons ListBoxItems

I Have a listbox defined like below :
<ListBox x:Name="lstMedias" ItemsSource="{Binding Medias}" Width="Auto" Height="Auto">
<ListBox.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Name}" Tag="{Binding Name}" Click="Button_Click" Command="{Binding Path=LoadSimpleMoviePopupCommand}">
<Button.Resources>
<Converters:LoadMovieMultiConverter x:Key="LoadMovieMultiConverter" />
</Button.Resources>
<Button.CommandParameter>
<MultiBinding Converter="{StaticResource LoadMovieMultiConverter}">
<MultiBinding.Bindings>
<Binding ElementName="DragDropCanvas" />
<Binding Path="Tag" RelativeSource="{RelativeSource Self}" />
</MultiBinding.Bindings>
</MultiBinding>
</Button.CommandParameter>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
When Trying to call command LoadSimpleMoviePopupCommand, command is not called, but when calling click event, event is raised.
Do You have an idea why ? It is a normal behavior ? Do we have to trick like ListBoxItem doubleclick ?
Probably because the binding failed. Check the output window of VS and see if there are any binding errors. I suspect the LoadSimpleMoviePopupCommand property is not on your data item class (ie. your Media class).
had the same problem, try this
<Button Command="{Binding DataContext.YourCommand,RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"
it's quite normal, he can't find your command binding inside the listbox because you set something like
<DataTemplate DataType ...
in that listbox so he'll be looking for that binding inside the datatype and not the viewmodel (I assume :)

WPF, passing variable to converter inside data template

I assume this is possible but not sure how to do it. I need to pass the value of a class level variable to a converter, from within side a data template.
<DataTemplate x:Key="ResponseItemTemplate">
<StackPanel Orientation="Horizontal" >
<StackPanel.Visibility>
<MultiBinding Converter="{StaticResource VisibilityConverter}">
<Binding Path="Key"/>
<Binding Path="CurrentLanguage"/>
</MultiBinding>
</StackPanel.Visibility>
<TextBox Width="200" Text="{Binding Value}" />
</StackPanel>
</DataTemplate>
The 'Key' value exists on the response item for the data template so this gets passed correctly, whereas the CurrentLanguage is a class variable and I can't get that to pass properly to the converter. Any ideas?
Thanks for the replies, this is what I needed to use in the end:
<Binding Path="DataContext.CurrentLanguage" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type Window}}"/>
You can use the binding object as follows:
<Binding Source="{x:Static local:DataObject.MyData}" />
See: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/c94682e5-ad16-42f9-973f-fd7588a9c0b5.
If you define the converter as a resource, which you have, you can access it in the code behind. Once you have the converter you can then set a property on it.
var myVisConverter = (VisibilityConverter)window.Resources["VisibilityConverter"];
myVisConverter.CurrentLanguage = ...
EDIT Ok, if you're trying to get access to the parent DataContext from within the DataTemplate, there's a couple of options. Easiest is to name the control with the correct DataContext, then bind to that control like so...
<Binding Path="DataContext.CurrentLanguage" ElementName="nameGivenToElement" />
Josh Smith wrote an article with more ways of getting inherited DataContexts.

Resources