Multiline Combobox in WPF - wpf

I'm trying to find an example of a multi line user editable combobox for WPF. We've tried various things with a custom template but can't make it work. The specific problem we're trying to solve is displaying a list of addresses in a drop down where the user can type in new ones at the same time. Typing into a combobox is no problem.. multi line is killing us though.

If we want show Textbox in ComboBox we can override the ItemTemplate of ComboBox. And to display multiline text we can set AcceptReturn="True" for TextBox.
<ComboBox Width="250" Height="30" >
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBox AcceptsReturn="True" Width="200" Height="100"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Is this what you need or am I missing something?

Related

Why is my Powershell WPF data binding pulling System.Windows.Controls.ComboBoxItem: Test 1 instead of Test 1

I'm learning how to use Powershell to create WPF forms. I have a ComboBox full of items, and when selected, they should populate a TextBox. I used a data binding to connect the Text property of the TextBox to the currently selected ComboBox item. But when I select an item, it populates as
System.Windows.Controls.ComboBoxItem: Test 1 instead of just Test 1.
Example Program Output
[xml]$Form = #"
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Title="Test Window" Height="200" Width="400">
<StackPanel>
<ComboBox Name="ComboBox1" Margin="10">
<ComboBoxItem>Test 1</ComboBoxItem>
<ComboBoxItem>Test 2</ComboBoxItem>
</ComboBox>
<TextBox Name="textBox" Margin="10" Text="{Binding ElementName=ComboBox1, Path=SelectedValue}"/>
</StackPanel>
</Window>
"#
$NR=(New-Object System.Xml.XmlNodeReader $Form)
$WIN=[Windows.Markup.XamlReader]::Load( $NR )
$WIN.Showdialog()
I've seen some other ways to do this in C#, but I'm trying to do this as just a Powershell script.
The best approach is probably to just make the ComboBox editable and discard the TextBox-based approach:
<ComboBox Name="ComboBox1" Margin="10" IsEditable="True">
...
This allows users to not only choose text (ComboBoxItems) from the drop-down, but also allows them to enter and modify the current text while the ComboBoxItems themselves remain untouched/unchanged.
However, if it is indeed desired to change the text of the ComboBoxItems themselves through a TextBox, you would need to bind against the Content property of the ComboBoxItem. Like so:
<TextBox Name="textBox" Margin="10" Text="{Binding SelectedItem.Content, ElementName=ComboBox1}"/>
After editing the text in the textbox, the item in the ComboBox will change accordingly (when the textbox loses focus).
If you want the ComboBoxItem to follow the edits in the textbox in "real-time", change the binding to:
Text="{Binding SelectedItem.Content, ElementName=ComboBox1, UpdateSourceTrigger=PropertyChanged}"

ListBox with copy paste feature

I am using MVVM approach, my UI needs to provide a simple copy paste area (something like TextBox) to the user and once user enters the text, I need to convert all newline separated text into list items - list items because I want to highlight individual items with errors, if any.
It should be seamless for the user- user should only see List items and should be able to edit them later.
Hence, basically I need a ListBox (for the programmer) which acts like a textbox (for the user). How can I achieve this?
I have implemented this using a Grid with TextBox & ListBox in the same Row, but with some overlap so that user can paste text in textbox and as soon as user enters the text, viewmodel separates the newlines into listitems. It is working but I am facing many issues (like clearing the textbox, etc.). I am looking for better more efficient solution if any. Below is the code snippet from xaml:
<Grid>
<TextBox AcceptsReturn="True" VerticalAlignment="Stretch" BorderBrush="Transparent"
Text="{Binding TextBoxData, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}">
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding OnNewLineCommand}"/>
</TextBox.InputBindings>
</TextBox>
<ListBox ItemsSource="{Binding ListBoxItems}" Margin="0,20,0,0" BorderBrush="Transparent" FocusVisualStyle="{x:Null}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding}" BorderBrush="Transparent"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListBox>
</Grid>
Thanks,
RDV

How to handle Validations on Custom Control

I recently wrote my first custom control, an autocomplete textbox. Its Controltemplate consists of something like this
<Grid >
<Border/>
<TextBlock x:Name="Label"/>
<TextBox x:Name="TextLabel"/>
</Grid>
The first Textblock is used as a Label, the second one shows the content. The TextLabel binds on an Object, let's call it Customer If the underlying search doesn't find a Customer object, I want to show the errortemplate. When defining the TextLabel like this
<TextBox x:Name="PART_Editor"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Validation.ErrorTemplate="{DynamicResource ValidationErrorTemplate}"
Style="{StaticResource TransparentTextBoxStyle}"
Text="{Binding Path=Text, RelativeSource={RelativeSource Mode=TemplatedParent},
Mode=TwoWay, ValidatesOnNotifyDataErrors=True,
NotifyOnValidationError=True,
ValidatesOnDataErrors=True,
UpdateSourceTrigger=PropertyChanged}" >
</TextBox>
the Validation is made and the error template of the textbox is shown. Unfortunately the Red Border is only around the inner TextBox and not around the whole custom control which looks just not good.
I was wondering how to achieve two things:
How can the ErrorTemplate of the CustomControl be triggered when one of the child-validations fail?
Do I have to specify all these NotifyOnValidationerror properties or is it possible to catch all errors on entity level and show the same ErrorTemplate
If you need additional Information, please just ask

WPF XAML Binding

Hello
I have a problem with a binding that I want to do and can't find any information on how to do it.
Basically I want to bind an object to a property of another object.
For example
<TextBox Text="test" Tag="{Binding ElementName=TxtBx2}" x:Name="TxtBx1"/>
<TextBox Text="test" x:Name="TxtBx2"/>
This is kind of weird but it would help on the code that i'm implementing, so on a property of one object I want to have another object bind in xaml.
I don't know if this is possible, any pointers would be helpful
Thanks, Ruben
That is how you do it; you just need to specify the Path.
<TextBox Text="test" Tag="{Binding ElementName=TxtBx2, Path=Text}" x:Name="TxtBx1"/>
<TextBox Text="test" x:Name="TxtBx2"/>
If you are wanting the DataContext of the TextBox; then your Path would change accordingly.
<TextBox Text="test" Tag="{Binding ElementName=TxtBx2, Path=DataContext}" x:Name="TxtBx1"/>
<TextBox Text="test" x:Name="TxtBx2"/>
If you are needing to use the Tag property within a WPF application you might want to re-evaluate your approach as I have yet to use the Tag property since moving from WinForms as that need has been replaced by leveraging the data binding functionality within WPF.
UPDATE:
If your goal is to bind to a given control versus a property on the control; then don't specify the property name within the Path.
Based on your goal; attached behaviors would be a better approach and allow you to wrap the functionality within the extended DataGrid.
<TextBox Text="test" Tag="{Binding ElementName=TxtBx2,Path=Text}" x:Name="TxtBx1"/>
<TextBox Text="test" x:Name="TxtBx2"/>
Assuming you want the value of the Text property of TxtBx1 to be the value of the Text property in TxtBx2, you would use:
<TextBox x:Name="TxtBx1" Text="{Binding ElementName=TxtBx2, Path=Text}" />
<TextBox x:Name="TxtBx2" Text="test" />
Update
Assuming (possibly incorrectly again!) that you want to bind the TxtBx1 element to the Tag of TxtBx2, you would use:
<TextBox x:Name="TxtBx1" Text="test" />
<TextBox x:Name="TxtBx2" Tag="{Binding ElementName=TxtBx1}" Text="test" />
Just out of interest, why do you want to do such a thing?
Update 2
Assuming that you have a Datagrid that you've extended from the wpftoolkit datagrid and a user control that is a pager for that Datagrid, and when you move to another page you need to do some processing on the datagrid, then why don't you just either update the datagrid in your page change event (if using code behind), or update the items that the datagrid is bound to in your page change verb on your view model (if using MVVM)?
Well, it does make sense to bind to an entire object(not to any specific property) with items control such as this:
<ListBox x:Name="pictureBox"
ItemsSource=”{Binding Source={StaticResource photos}}" …>
......
</ListBox>

WPF Datagrid Template column edit event and alternating column color

I have been using WPF for quiet sometime. I know DataGrid in WPF does not have a Column collection as dependency property so columns cannot be added dynamically.
The application I am developing is highly dynamic so the number of columns are not known. So I am creating DataGridTemplate columns from code behind.
Problem 1 : I want alternating columns to have different background color. How do I do it programatically?? (DataGridTemplateColumn doesnot have a Background property so I am not able to figure out a solution)
Problem 2 : My DataGridTemplateColumn has a DataTemplate in which I have a StackPanel with 2 TextBoxes in it. There is an event in DataGrid called CellEditing Event which fires when we edit a cell. It works for default column, but for my column if I edit those TextBoxes, the event is snot getting fired!!! So how do I achieve it??
(I sometimes get amazed by WPF !!!)
Problem Zero You can have the columns in a datagrid generated for you if you use AutoGenerateColumns="true" when you set up your datagrid. It won't add columns dynamically later, but it might if you reset the itemssource? (not positive on that one)
Problem One DataGrid has properties AlternatingRowBackground and AlternationCount to set up alternating row backgrounds. But i don't see anything for alternating column backgrounds in the grid itself. You could do it inside your datatemplate, though:
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Background="Red" Foreground="White">I'm Red</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
But i still see a margin inside that even with margin=0, so the cells look funny if you use any really obvious colors.
Problem Two do you mean the CellEndEditing event? Because i don't see any other cell editing events. I tried the following:
<DataGrid ItemsSource="{Binding}" AutoGenerateColumns="False" CellEditEnding="DataGrid_CellEditEnding">
<DataGrid.Columns>
<DataGridTextColumn Header="A" Binding="{Binding Field0}" />
<DataGridTemplateColumn Header="BC">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Field1}"/>
<TextBlock Text="{Binding Field2}" />
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding Field1}"/>
<TextBox Text="{Binding Field2}" />
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
And my DataGrid_CellEditEnding event handler gets called whenever either of the textboxes in the CellEditingTemplate lose focus, whether data changed or not, so things appear to be working for me.
Are you using some other DataGrid than the "built in" WPF one?

Resources