Autocompletebox doesn't clear keyboard strokes - c#

In an application of mine, I'm using the WPF autocomplete box from the wpf toolkit. I'm implementing it via the MVVM pattern. The binding works fine, but I have a small problem when trying to clear the content of the autocompletebox. Setting the bound property in the viewmodel to null, clears the text only partially (all text entered via the keyboard is not cleared - i.e. if I enter CH when fetching all the cities and select Chicago and the set the bound property to null, the CH is not being cleared , the rest ICAGO is.)
The XAML looks like this:
<my:AutoCompleteBox Grid.Row="0"
Grid.Column="1"
HorizontalAlignment="Left"
Margin="0,6,0,0"
Name="acTown"
SelectedItem="{Binding NewTown, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ValueMemberBinding="{Binding Converter={StaticResource TownConverter}}"
Populating="Populating"
VerticalAlignment="Top"
Height="Auto"
</my:AutoCompleteBox>
The method in the viewmodel to clear the box is:
public void ClearTown()
{
NewTown = null;
OnPropertyChanged("NewTown");
}
I can't figure out what's wrong with the code, or is this just a bug in the autocompletebox?
After extensive research, I found this article: How do you clear the Silverlight AutoCompleteBox SearchText using MVVM, but it does not offer a solution. There seems to be a SearchText property on the AutoCompleteBox that is readonly and cannot have a setter

Finally got it. If anyone's interested, the solution is to simply change NewTown = null to NewTown = new NewTown() in the ClearTown function.

Related

WPF - TextBox not binding properly when set to readonly

I have TextBox that I'm using to add (only to add and not read) file path into DB. Text property is set when user selects certain file (OpenFileDialog). So, I set it in readonly state and it won't bind properly. When I remove readonly it works fine.
<Button Name="btnAddFile" Content="+" HorizontalAlignment="Left" Width="23" Height="23" Click="AddFilePath"/>
<TextBox Name="tbxFilePath" Height="23" Text="{Binding FilePath}" Width="364" IsReadOnly="True"/>
When I use:
Text="{Binding FilePath, Mode=OneWayToSource}"
it sometimes work but most of the time it doesn't (?!). I could use TextBlock or Label but I would really like to understand what is going on and use TextBox.
I'm using Entity Framework but don't think it does matter.
Question: How can I programmatically add text to TextBox control which is readonly and be able to bind it.
EDIT: I figured out what the problem is. When I set focus on TextBox after I set it's Text property from code-behind, it works. I guess it has to notify that Text is changed when I do it from code-behind. How to do that?
Have you tried using OneWay Binding?
MSDN reads:
OneWay Updates the binding target (target) property when the binding source (source) changes. This type of binding is appropriate if the control being bound is implicitly read-only.
Which I think covers your scenario.
The target is your TextBox Text property and your source is your FilePath property on your ViewModel.
Use:
Text="{Binding FilePath, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
EDIT
This answer assumes you have implemented INotifyPropertyChanged on your ViewModel.
EDIT
The correct binding mode is OneWayToSource. Confirmed by OP.

How to display data from datagrid to textbox in wpf c#

Can some1 please give me an example or a code, how to display data from datagrid to textbox in c# - wpf app.
I've tried to do it like in Windows Forms application, but the code doesn't work.
if (e.RowIndex >= 0)
{
DataGridViewRow row = this.dataGridView1.Rows[e.RowIndex];
name.Text = row.Cells["Name"].Value.ToString();
lastName.Text = row.Cells["LastName"].Value.ToString();
userName.Text = row.Cells["UserName"].Value.ToString();
password.Text = row.Cells["Password"].Value.ToString();
}
First, WPF is not WinForms, trying to code thing the same way is just going to cause you pain. What you are trying to do is actually really easy in WPF! The shortest solution is to bind directly to the DataGrid SelectedItem property:
<DataGrid x:Name="UserGrid" ItemsSource="{Binding Users}">
...
</DataGrid>
<TextBox Text="{Binding ElementName=UserGrid, Path=SelectedItem.Name}"/>
...More of the same...
Now this assumes that the DataGrid is bound to a collection of the "User" class (which it absolutely should be) in your ViewModel (NOT your code-behind). The other way would be to bind SelectedItem and then have the other controls bind to that, like so:
<DataGrid x:Name="UserGrid" ItemsSource="{Binding Users}" SelectedItem="{Binding CurrentUser}">
...
</DataGrid>
<TextBox Text="{Binding Path=CurrentUser.Name}"/>
...More of the same...
Of course you now need a "CurrentUser" property in your ViewModel to bind to. Both ways are equally valid approaches, just decide which you like better. The second is better if you need the "CurrentUser" object for something else in code, the first is a bit quicker and doesn't have the shell property if you don't need it. In case you haven't done anything with MVVM, here is a great tutorial (MSDN).

WPF Combobox issue

I have a combo box in a wpf c# application. In the xaml i am trying to do the following.
The ItemsSource comes from one variable.
SelectedItem sets a value on another variable
But i want the text displayed to come from a new variable.
How do i stop making the selected itemssource appear as the main text?
<ComboBox x:Name="ComboPlay" FontSize="14" MinHeight="20" Margin="0,2,4,4" Grid.Row="1" Grid.Column="3" MinWidth="160"
ItemsSource="{Binding ComboBoxList}"
SelectedItem="{Binding OutputChannel.Value, Converter={StaticResource ResourceKey=ValueToStringConverter}}" Grid.ColumnSpan="1"
IsEnabled="{Binding IsDriveChoiceEnabled}"
HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
If you mean changing the display of the item currently selected (the portion of the control shown when the dropdown is closed), take a look at Can I use a different Template for the selected item in a WPF ComboBox than for the items in the dropdown part?
Honestly, a quick search dug up that one and many similar ones. Probably the simplest way, like the linked answer, is to figure out if your item is wrapped in a ComboBoxItem and display it differently then. Or you could re-template the ComboBox. Or you could derive from it (and re-template it) and provide a separate dependency property for the template of the selected item, if you expect to reuse it in different contexts. The sky's the limit.

WPF Combobox with clear button

I am trying to create a WPF ComboBox control which contains a clear button when something is selected. The control should have two states: if something is selected the control looks like a label with a clear button. If nothing is select then a normal ComboBox is display. The two states are showing in the picture below.
Researching my problem I came across the following SO questions which are very similar to mine:
Adding a button to a combobox in wpf
How to subclass a WPF ComboBox to add an extra button
Both suggest subclassing the ComboBox providing a modified template with the extra button. But this is where I am a tad confused. The answer by John Bowen to the second linked question indicates that I should copy the ComboBox's default template; modifying it to include a button getting the template from Blend. Not being proficient with blend I found the template on MSDN here:
http://msdn.microsoft.com/en-us/library/ms752094(v=vs.85).aspx
My problem is I am not quite sure what I should change. Looking at the Default template I think I need to do something along the lines of:
Create a new 'IsSelected' property which I can hook triggers to.
Add a control template for a Clear Button with trigger attached to IsSelected which hides the button.
Attached a IsSelected Trigger to the ComboBoxToggleButton control template to hide it upon selection.
Somehow re-size the PART_EditableTextBox textbox in the ComboBox Template when IsSelected is true.
Does this seem right and any pointers on how I do it or other suggestions if I am barking up the wrong tree.
Maybe you will accept a simpler solution - just place a TextBlock with a Button above your ComboBox?
The xaml will look like this:
<Grid>
<ComboBox ItemsSource="{Binding ...}" x:Name="cbox"/>
<Grid Background="Gray" Visibility="{Binding SelectedItem, ElementName=cbox, Converter={StaticResource NullItem2Visibility}}">
<TextBlock Text="{Binding SelectedItem, ElementName=cbox}" HorizontalAlignment="Left"/>
<Button Content="Clear" HorizontalAlignment="Right" Click="ClearItem"/>
<Grid>
</Grid>
Codebehind will have method ClearItem:
public void ClearItem(object sender, EventArgs e){
cbox.SelectedItem=null;
}
And the converter to show and hide textblock and a button:
class NullItem2Visibility:IValueConverter{
public object Convert(object value, Type type, object parameter, CultureInfo i){
return value == null ? Visibility.Collapsed : Visibility.Visible;
}
public object ConvertBack(...){...}
}

WPF Combobox binding: can't change selection

After wasting hours on this, following on the heels of my Last Problem, I'm starting to feel that Framework 4 is a master of subtle evil, or my PC is haunted.
I have three comboboxes and a textbox on a WPF form, and I have an out-of-the-box Subsonic 3 ActiveRecord DAL.
When I load this "edit record" form, the comboboxes fill correctly, they select the correct items, and the textbox has the correct text. I can change the TextBox text and save the record just fine, but the comboboxes CANNOT BE CHANGED. The lists drop down and highlight, but when you click on an item, the item selected stays the same.
Here's my XAML:
<StackPanel Orientation="Horizontal" Margin="10,10,0,0">
<TextBlock Width="80">Asset</TextBlock>
<ComboBox Name="cboAsset" Width="180"
DisplayMemberPath="AssetName"
SelectedValuePath="AssetID"
SelectedValue="{Binding AssetID}" ></ComboBox>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="10,10,0,0">
<TextBlock Width="80">Status</TextBlock>
<ComboBox Name="cboStatus" Width="180"
DisplayMemberPath="JobStatusDesc" SelectedValuePath="JobStatusID"
SelectedValue="{Binding JobStatusID}" ></ComboBox>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="10,10,0,0">
<TextBlock Width="80">Category</TextBlock>
<ComboBox Name="cboCategories" Width="180"
DisplayMemberPath="CategoryName"
SelectedValuePath="JobCategoryID"
SelectedValue="{Binding JobCategoryID}" ></ComboBox>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="10,10,0,0">
<TextBlock Width="80">Reason</TextBlock>
<TextBox Name="txtReason" Width="380" Text="{Binding Reason}"/>
</StackPanel>
Here are the relevant snips of my code (intJobID is passed in):
SvcMgrDAL.Job oJob;
IQueryable<SvcMgrDAL.JobCategory> oCategories = SvcMgrDAL.JobCategory.All().OrderBy(x => x.CategoryName);
IQueryable<SvcMgrDAL.Asset> oAssets = SvcMgrDAL.Asset.All().OrderBy(x => x.AssetName);
IQueryable<SvcMgrDAL.JobStatus> oStatus = SvcMgrDAL.JobStatus.All();
cboCategories.ItemsSource = oCategories;
cboStatus.ItemsSource = oStatus;
cboAsset.ItemsSource = oAssets;
this.JobID = intJobID;
oJob = SvcMgrDAL.Job.SingleOrDefault(x => x.JobID == intJobID);
this.DataContext = oJob;
Things I've tried:
Explicitly setting IsReadOnly="false" and IsSynchronizedWithCurrentItem="True"
Changing the combobox ItemSources from IQueryables to Lists.
Building my own Job object (plain vanilla entity class using INotifyPropertyChanged).
Every binding mode for the comboboxes.
ItemsSource="{Binding}"
The Subsonic DAL doesn't implement INotifyPropertyChanged, but I don't see as it'd need to for simple binding like this. I just want to be able to pick something from the dropdown and save it.
Comparing it with my last problem (link at the top of this message), I seem to have something really wierd with data sources going on. Maybe it's a Subsonic thing?
EDIT: For some reason the set accessor is hit only on the AssetID property and only the first time. WPF is now heading for WTF :)
EDIT 2: You gotta be kidding me- I've removed the binding (ie it only has a displaymemberpath, a valuememberpath and an itemssouce) and it's STILL doing it! It accepts your first selection, and then won't change.
WPF Combo Boxes will not change the selected item if the currently selected item and the item that was just selected are considered equal by the object.Equals() method called on the newly selected object (i.e newlyslected.Equals(previoslySelected) ).
Overriding the Equals method on the class your binding the combobox items, should resolve the issue your are seeing.
I've narrowed it down to the Subsonic objects used as ComboBoxItems.
If you create a new class that uses exactly the same code as the relevant parts of the Subsonic one, it works.
If you use POCOs/datatables for the combos and Subsonic for the record being edited, it works.
But if you use Subsonic for both, it doesn't.
I had hoped to extend the subsonic objects and not have to code a full-blown BLL tier. Looks like I'm faced with doing that or throwing out Subsonic for the DAL. I might post a more specific question for the Subsonic folks.
Many thanks to all who contributed.
Old topic but I had the same problem and difficulty finding solution. This might help someone else.
Clue is above in WPF not detecting a different item has been seleted by user. (Symptom - event ComboBox_SelectionChanged only fires on first selection)
My scenario - lookup combo populated from IList built from a DISTINCT query. In this case the result of using NHibernate ICriteria.SetResultTransformer which only returns SOME fields, importantly NOT including the unique entity ID.
Solution - loop thru' IList after retrieval and give each entity a unique ID. WPF sees them as individuals and behaves appropriately.
Its only a value lookup - its the value content I was after.
The 'temporary' entities are never persisted. In this case it was a better approach than messing with overriding the object's Equals method for the sake of a simple GUI issue. An alternative would be to just copy or tranform the list into a format where WPF uses the value field to determine 'difference'...
Sounds like the field is somehow readonly, or that your change isn't being persisted. After the binding sets the new value, it will re-read the property to ensure that it was actually changed. If your property returns the old value, then it'll be re-selected in the combo box, giving the appearance that the value never changed.
I don't know that DAL, but can you step through the property setter code? You might also have an issue with type conversion.
EDIT reading your comment about the red rectangle -- it sounds as though your property (or something to do with the binding) is raising an exception. Unless, of course, you're using data validation in your UI. You might turn 'Break on all exceptions' in the debugger's settings, assuming you're using Visual Studio.
EDIT 2 You should check the VS Output pane for any error messages related to binding. You can also read this blog post which gives more info on debugging bindings.
It's hard to tell from a small sample of your code but try commenting out the line:
//this.DataContext = oJob;
and see if this helps.
Setting the DataContext and ItemsSource might be causing a conflict.
Did you write any global style for your combo box which may have a bug or something missing? Or are you using pure default styles for your combobox? Try removing any default styles applied.
Are you wiring up any events? If your code hooks up for event like PreviewMouseLeftButtonUp and marks event as handled then probably combobox may ignore and wont select anything.

Categories

Resources