bind user control to contentcontrol validation rules not firing - c#

I have many user controls and i have main window which contains a content control and list box when user select from list box i bound the selected user control to the content control the problem is when the user control bound for the first time the validation rules is appears but when user control bound for the second time the validation rules disappear what is the problem ?
here is the main window :
<Grid>
<ListBox x:Name="FormsListBox" Margin="0,5,0,5" Grid.Row="1" Grid.Column="0" Width="180" ItemsSource="{Binding Formlist}" SelectedItem="{Binding SelectedFormInfo}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="Resources/Capture.PNG" ></Image>
<TextBlock Text="{Binding Path=FormName}"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<StackPanel Grid.Row="1" Grid.Column="1" x:Name="MainStackPanel" >
<ContentControl Content="{Binding Path=SelectedFormInfo.MainForm}">
</ContentControl>
</StackPanel>
</Grid>
here is the sample of validation role in user control:
<StackPanel Width="315" Margin="20,0,10,0">
<TextBox x:Name="TxtWeaponNumber" Width="315">
<TextBox.Text>
<Binding Path="SelectedWeapon.weaponNumber" Mode="TwoWay"
UpdateSourceTrigger="PropertyChanged" ValidatesOnNotifyDataErrors="True"
ValidatesOnDataErrors="True" NotifyOnValidationError="True"
NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True">
<Binding.ValidationRules>
<validationRules:RequiredRule ValidatesOnTargetUpdated="True" ValidationStep="RawProposedValue" />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</StackPanel>
Note: MainForm in SelectedFormInfo contains thee selected user control

i set my user control in AdornerDecorator and the Validation did not disappear

Related

WPF Binding in textblock does not work but in its tooltip does

I have a weird issue.
In my application (witten with C# .net framework 4.8 with Microsoft's MVVM toolkit) I have a ListView bound to a BindingList<VisualMachine>, everything works as expected.
Now I wanted to add to the Itemtemplate a DockPanel with data from another BindingList<PreviewParameter> (another property of the original VisualMachine object ).
This is when weirdness starts: In this new ItemTemplate I have a Grid that contains an Image, a TextBlock and a Tooltip. The TextBlock and the Tooltip are bound to the same object, but only the ToolTip actually show data!
I feel like it's some DataContext Issue, but I am not able to pin it... Can anybody give me some advice?
Thanks!
The code:
<ListView Name="MachinesListView" Margin="2" HorizontalContentAlignment="Stretch" BorderThickness="0" DockPanel.Dock="Top" ItemsSource="{Binding Path=Machines}" PreviewMouseRightButtonDown="ListView_PreviewMouseRightButtonDown" SelectedItem="{Binding Path=SelectedMachine}">
<ListView.ItemTemplate>
<DataTemplate>
<!-- Other stuff -->
<DockPanel>
<!--#region PREVIEW PARAMETERS PANEL-->
<WrapPanel HorizontalAlignment="Stretch" DockPanel.Dock="Bottom" Visibility="{Binding Path=PreviewParameters.Count, Converter={StaticResource CountToVisConverter}}">
<ListView ItemsSource="{Binding Path=PreviewParameters}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid MinWidth="50">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="25"/>
<ColumnDefinition Width="Auto" MinWidth="25"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="{Binding Path=Icon, Converter={StaticResource ResourceKey=BmpToBmpImageConverter}}"/>
<TextBlock Grid.Column="1" MaxWidth="100" DataContext="{Binding}">
<TextBlock.Text>
<!-- THIS DOES NOT APPEAR -->
<MultiBinding StringFormat="{}{0} [{1}]}">
<Binding Path="Parameter.VisualizedValue"/>
<Binding Converter="{StaticResource ParamToEnumDescConverter}" Path="Parameter"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
<Grid.ToolTip>
<TextBlock MaxWidth="100" TextWrapping="Wrap">
<TextBlock.Text>
<!-- THIS DOES APPEAR -->
<MultiBinding StringFormat="{}{0} [{1}] - {2} TEST:{3} {4}">
<Binding Path="Parameter.Reference"/>
<Binding Path="Parameter.SetupIndex"/>
<Binding Path="Description"/>
<Binding Path="Parameter.VisualizedValue"/>
<Binding Converter="{StaticResource ParamToEnumDescConverter}" Path="Parameter"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</Grid.ToolTip>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</WrapPanel>
<!-- Other stuff -->
</DockPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
What happens:
I found it.
There was a } in the StringFormat property of the TextBlock's MultiBinding.
So instead of
<MultiBinding StringFormat="{}{0} [{1}]}">
it should be
<MultiBinding StringFormat="{}{0} [{1}]">
And BAM! Now it works.
I'll leave the question as the following reminder to anybody: "Write your code, review it, than go take a coffee o chat a little and then come back. You'll be amazed on how blind you could be."

Making a ToolTip not visible

There is an icon that I want to always be visible, but I want the tooltip to be conditionally visible. Here is the code that I currently have:
<TextBlock Grid.Row="2"
Grid.Column="0"
VerticalAlignment="Center"
FontSize="15"
Visibility="{Binding IsConnected, Converter={StaticResource BooleanToVisibilityConverter}}">
<fa:ImageAwesome Icon="{Binding Path=BatteryLevelIcon, UpdateSourceTrigger=PropertyChanged}"
Height="20"
Width="20"
Foreground="Green"
Visibility="{Binding IsConnected, Converter={StaticResource BooleanToVisibilityConverter}}" />
<ToolTipService.ToolTip>
<TextBlock Visibility="{Binding IsCharging, Converter={StaticResource InvertedBooleanToVisibilityConverter}}">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}%">
<Binding Path="BatteryPercentage" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</ToolTipService.ToolTip>
</TextBlock>
So, I want the tooltip to only show up when IsCharging is false. The issue that I am having is that because the Visibility property is on the tooltip textblock instead of the tooltip itself, setting it to not visible only gives me a empty tooltip, instead of the tooltip not appearing at all. I have tried defining the content of the tooltip (textblock) in UserControls.Resources and then setting the textblock and IsEnabled, but it gave me the error:
a value of type tooltipservice cannot be added to a collection or dictionary of type inlinecolection
It doesn't seem there is an easy way to set the visibility for the tooltip. If anyone has any suggestions it would be greatly appreciated!
You could use ToolTipService.IsEnabled property for the purpose
ToolTipService.IsEnabled="{Binding IsToolTipVisible}"
Where IsToolTipVisible Where is the View Model property which dictates where to enable the tooltip
Complete Code
<TextBlock Grid.Row="2" ToolTipService.IsEnabled="{Binding IsToolTipVisible}"
Grid.Column="0"
VerticalAlignment="Center"
FontSize="15"
Visibility="{Binding IsConnected, Converter={StaticResource BooleanToVisibilityConverter}}">
<fa:ImageAwesome Icon="{Binding Path=BatteryLevelIcon, UpdateSourceTrigger=PropertyChanged}"
Height="20"
Width="20"
Foreground="Green"
Visibility="{Binding IsConnected, Converter={StaticResource BooleanToVisibilityConverter}}" />
<ToolTipService.ToolTip>
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}%">
<Binding Path="BatteryPercentage" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</ToolTipService.ToolTip>
</TextBlock>

Setting custom ToolTip for Border Control in WPF

I am working on internationalizing a WPF application. I am stuck at a situation where a ToolTip to be set near a border control which is to be concatenated like this:
RoleType : Manager
I am binding RoleType in ViewModel which has Manager, TechLead, Engineer etc. RoleType string is fixed and is translated in Resources file. Now in view, I need to concatenate and show the user who has logged in.
I tried MultiBinding but after login, my screen turns blackout. I cannot exit my application.
Here is the code I am trying:
<StackPanel Grid.Row="0" Orientation="Vertical" VerticalAlignment="Top">
<Border BorderBrush="{Binding BorderBrush}" HorizontalAlignment="Center" VerticalAlignment="Center" Height="auto" Width="auto"
Background="Transparent" >
<Border.ToolTip>
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} : {1}">
<Binding Path="Text" ElementName="{languageTranslation:Translate RoleType}" />
<Binding Path="Text" ElementName="{languageTranslation:Translate {Binding UserName}}" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</Border.ToolTip>
<ContentControl Height="65" VerticalContentAlignment="Top" HorizontalAlignment="Center" ContentTemplate="{StaticResource UserProfileIcon}"></ContentControl>
</Border>
What am I doing wrong? Converters are not required as it is only strings.

How to set a secondary control MaxWidth property to the same as another in a different container

I have this StackPanel in one grid on my form:
<StackPanel x:Name="panelWeelyBibleReading" Grid.Row="2" Grid.Column="0" Margin="2">
<Label>Bible Reading for Week:</Label>
<TextBox x:Name="textWeeklyBibleReading">PSALMS 60-68</TextBox>
</StackPanel>
<StackPanel Grid.Row="3" Grid.Column="0" Margin="2">
<Label>Opening Song:</Label>
<ComboBox x:Name="comboSongOpen" ItemsSource="{StaticResource SongTitles}">
<ComboBox.ItemTemplate>
<DataTemplate DataType="local:SongTitleItem">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Number, StringFormat='000 - '}" />
<TextBlock Text="{Binding Title}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
<ComboBox.MaxWidth>
<Binding Path="ActualWidth"
ElementName="textWeeklyBibleReading"/>
</ComboBox.MaxWidth>
</ComboBox>
</StackPanel>
Further down the form in a different grid I have this :
<StackPanel Grid.Row="3" Grid.Column="0" Margin="2">
<Label>Closing Song:</Label>
<ComboBox x:Name="comboSongEnd" ItemsSource="{StaticResource SongTitles}">
<ComboBox.ItemTemplate>
<DataTemplate DataType="local:SongTitleItem">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Number, StringFormat='000 - '}" />
<TextBlock Text="{Binding Title}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
<ComboBox.MaxWidth>
<Binding Path="ActualWidth"
ElementName="panelWeeklyBibleReading.textWeeklyBibleReading"/>
</ComboBox.MaxWidth>
</ComboBox>
</StackPanel>
Initially I tried using the same "textWeeklyBibleReading" for the MaxWidth in the second combo. But it doesn't work. No warnings. Just doesn't work. So I thought about applying a name to the previous StackPanel in teh hopes I could use it as some kind of access point. But it still doesn't work.
So my problem is that I need to set the MaxWidth on the second combo, which is in a different grid, but using the value that was calculated on the first grid combo. Am I making sense?
I would show the complete form markup if it helps.
You should edit to:
<ComboBox.MaxWidth>
<Binding Path="Width"
ElementName="textWeeklyBibleReading"/>
</ComboBox.MaxWidth>
<Binding Path=Width, ElementName=textWeeklyBibleReading/>
cause there is no property such as ActualWidth, instead it should be Width. And there is no need to write container name panelWeeklyBibleReading, just write ElementName that you need.
Update:
<ComboBox.ItemTemplate>
<DataTemplate DataType="local:SongTitleItem">
<StackPanel Orientation="Horizontal" MaxWidth="{Binding Path=Width,
ElementName=textWeeklyBibleReading}">
<TextBlock Text="{Binding Number, StringFormat='000 - '}" />
<TextBlock Text="{Binding Title}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
You should set MaxWidth of StackPanel of ComboBox cause outer StackPanel``(<StackPanel Grid.Row="3" Grid.Column="0" Margin="2">) which contains your ComboBox automatically sets Width to the outer StackPanel to your ComboBox. So I suggest to bind Width of your ComboBox to its ItemTemplate. Cause ItemTemplate has Data/template, then it is better to bind Width of ComboBox to StackPanel located into your DataTemplate.

Updating the source of a Listbox with a multibinding

I'm trying to get a multi-bound listbox to call the convert back method when items inside it change. Specifically I have a datatemplate that maps each entry to a checkbox and I'd like the source to be updated whenever a box is checked.
<ListBox x:Name="listBoxEdit" Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="3" Height="100" >
<ListBox.ItemsSource>
<MultiBinding Converter="{StaticResource selectedLoadsConverter}" >
<Binding Path="AvailableLoads"/>
<Binding Path="CurrentUnit"/>
</MultiBinding>
</ListBox.ItemsSource>
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Item1}" IsChecked="{Binding Item2}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I know the problem lies in the fact that I'm binding to to the ItemsSource property which is never actually being updated by the checkbox changing, but I can't figure out a good way to push the updates up to the source.

Categories