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.
I have this code:
<DataTemplate>
<Border>
<Border.ToolTip>
<ToolTip IsEnabled="True"
Placement="Right">
<ToolTip.VerticalOffset>
<MultiBinding Converter="{StaticResource OffsetConverter}"
ConverterParameter="Vertical">
<MultiBinding.Bindings>
<Binding RelativeSource="{RelativeSource Self}"/>
</MultiBinding.Bindings>
</MultiBinding>
</ToolTip.VerticalOffset>
<TextBlock Margin="0"
Padding="0"
TextAlignment="Left"
TextWrapping="Wrap"
MaxWidth="200"
Text="{Binding Description}" FontStyle="Italic">
</TextBlock>
</ToolTip>
</Border.ToolTip>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch" Margin="0">
<Image Height="16" Width="16" Style="{StaticResource AutoCompletionImageStyle}" Margin="0"/>
<Label Content="{Binding DisplayText}" Margin="0" Padding="0"/>
</StackPanel>
</Border>
</DataTemplate>
And this converter :
public object Convert(object[] values, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
AutoCompletionViewModel.OffsetType offsetType = (AutoCompletionViewModel.OffsetType)Enum.Parse(typeof(AutoCompletionViewModel.OffsetType), parameter.ToString());
ToolTip tooltip = values[0] as ToolTip;
Border border = tooltip.PlacementTarget as Border;
double aCalculatedOffset = 0.0;
return aCalculatedOffset;
}
I need to calculate the offset of the tooltip based on some properties of the Border. The tooltip appears relative to the border and manually changing the offset works as expected. However when I try to access the PlacementTarget property of the ToolTip in the converter it is null...
So, although the ToolTip is a direct child of the Border and should have it as a placement target, in the code it is null. Any idea what I am missing here?
I also tried passing the border with <Binding RelativeSource="{RelativeSource AncestorType={x:Type Border}}"/> to no avail.
I am really confused since, if the border is not the logical or visual parent of the ToolTip how does the ToolTip places itself correctly?!
I managed to find a workaround :
<DataTemplate>
<Border ToolTipOpening="OnAutoCompletionBorderToolTipOpening">
<Border.ToolTip>
<ToolTip>
<ToolTip.Style>
<Style>
<EventSetter Event="ToolTip.Opened" Handler="ToolTipOpenedHandler" />
</Style>
</ToolTip.Style>
</ToolTip>
</Border.ToolTip>
</Border>
</DataTemplate>
Code behind:
private void ToolTipOpenedHandler(object sender, RoutedEventArgs e)
{
ToolTip toolTip = (ToolTip)sender;
UIElement target = toolTip.PlacementTarget;
var rect = toolTip.PlacementRectangle;
}
The target here is not null, rather the Border...
I am pretty sure this is some WPF bug. Hopefully someone will be helped by this post.
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
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.
I'm working with WPF recently. Now, i'm facing a problem.
I have a button "ADD", every time click on this will add a new row with some contents. Those contents are shown below-
<TextBox Text="{Binding Name}" Margin="10,10" Height="20" ></TextBox>
<TextBox Text="{Binding City}" Margin="10,10" Height="20" ></TextBox>
<TextBox Text="{Binding Age}" Margin="10,10" Height="20"></TextBox>
<TextBox Text="{Binding Count}" Margin="10,10" Height="20" ></TextBox>
<Button Content="M1" Margin="10,10" Height="20"/>
<Button Content="M2" Margin="10,10" Height="20"/>
<Button Content="M3" Margin="10,10" Height="20"/>
</WrapPanel>
</Grid>
Here, at the end there are three buttons M1,M2,M3. But, I don't need this all three buttons every time. I may need only M1 or only M2 or only M3 or M1,M2 etc.
How can I do this in c#?
Actually i don't even know, am i in the right way?
Thanks in advance.
I would highly recommend looking into the MVVM design pattern when working with WPF
That said, I would bind my XAML to an ObservableCollection<SomeObject>, and clicking the AddButton would add a new SomeObject to the ObservableCollection. This would make the UI automatically add the new row when the collection gets updated, and SomeObject could have properties for IsM1Visible, IsM2Visible, and IsM3Visible which determines which buttons are visible.
For example,
Class SomeObject would have
string Name;
string City;
int Age;
int Count;
bool IsM1Visible;
bool IsM2Visible;
bool IsM3Visible;
The XAML would look something like this:
<ItemsControl ItemsSource="{Binding SomeCollection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBox Text="{Binding Name}" Margin="10,10" Height="20" ></TextBox>
<TextBox Text="{Binding City}" Margin="10,10" Height="20" ></TextBox>
<TextBox Text="{Binding Age}" Margin="10,10" Height="20"></TextBox>
<TextBox Text="{Binding Count}" Margin="10,10" Height="20" ></TextBox>
<Button Content="M1" Visibility="{Binding IsM1Visible, Converter="{StaticResource BooleanToVisibilityConverter}" Margin="10,10" Height="20"/>
<Button Content="M2" Visibility="{Binding IsM2Visible, Converter="{StaticResource BooleanToVisibilityConverter}" Margin="10,10" Height="20"/>
<Button Content="M3" Visibility="{Binding IsM3Visible, Converter="{StaticResource BooleanToVisibilityConverter}" Margin="10,10" Height="20"/>
</WrapPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
And the Add Button's Click event would look something like this:
void AddButton_Click(object sender, EventArgs e)
{
var newItem = new SomeItem
{
Name = "Something",
City = "Something",
Age = 30,
Count = 2,
IsM1Visible = true,
IsM2Visible = false,
IsM3Visible = true
};
SomeCollection.Add(newItem);
}
You could use DataBinding if the amount of buttons is dependent on the size of a list/collection.
<ItemsControl ItemsSource={Binding Ms}>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Name}" Command={Binding ThingToDoWhenClickedCommand}/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
This will generate exactly the amount of buttons that is in the Ms collection/List that is in the DataContext.
You can just add the buttons through your code-behind files and put an if structure around the buttons to determine what button should be loaded.
Are you using MVVM?
If so then this is easy. Just create a ButtonViewModel object that represents one of your buttons and expose an ObservableCollection of them from your main ViewModel.
In your view just have a ListView, or just an ItemsControl bound to the collection, and a DataTemplate that turns your ButtonViewModel into a button.
When the user clicks the Add button, add a new ButtonViewModel to your collection and the view will update itself to match.
First, let create a view model for a row. In that model you will have 3 bool properties, IsButton1Visible, IsButton2Visible, IsButton3Visible, or something like that with all properties you need to do binding on your row.
Second, your scenario is that when you click Add, new row will be added. So you have a list of Row_View_Model. On AddCommand, you will at a new Row_View_Model into the list. Here you have full control on what button you want to show.