How to "Set" the SelectedIndex in DevExpress ComboBoxEdit?
I tried both in XAML and in code behind, but the index was not set, it starts out with a blank item.
My XAML: [I can't see why this doesn't work, but it doesn't..]
<dxb:BarEditItem.EditSettings>
<dxe:ComboBoxEditSettings>
<dxe:ComboBoxEditSettings.Items>
<dxe:ComboBoxEditItem IsSelected="True">AAA</dxe:ComboBoxEditItem>
<dxe:ComboBoxEditItem>BBB</dxe:ComboBoxEditItem>
<dxe:ComboBoxEditItem>CCC</dxe:ComboBoxEditItem>
</dxe:ComboBoxEditSettings.Items>
</dxe:ComboBoxEditSettings>
</dxb:BarEditItem.EditSettings>
My C# code: [I'm getting the countStr correctly so I'm sure the ComboBoxEdit and the items are initialized and added ok, but SelectedIndex still don't set the index..]
* also I do not want to use EditValue to set the value, I need to use an integer (Index) to set it.
private void Foo_LinkControlLoaded(object sender,
DevExpress.Xpf.Bars.BarItemLinkControlLoadedEventArgs e)
{
BarEditItemLink link = (BarEditItemLink)sender;
countStr = ((ComboBoxEdit)link.Editor).Items.Count.ToString();
((ComboBoxEdit)link.Editor).SelectedIndex = 2;
}
There are no SelectedIndex or SelectedItem property within the editor settings (e.g. ComboBoxEditSettings).
But you can set the SelectedIndex, SelectedItem or EditValue properties of ComboBoxEdit via the editor style:
<dxb:BarEditItem x:Name="beiComboBox">
<dxb:BarEditItem.EditStyle>
<Style TargetType="dxe:ComboBoxEdit">
<Setter Property="SelectedIndex" Value="1"/>
</Style>
</dxb:BarEditItem.EditStyle>
<dxb:BarEditItem.EditSettings>
<dxe:ComboBoxEditSettings>
<dxe:ComboBoxEditSettings.Items>
<dxe:ComboBoxEditItem>AAA</dxe:ComboBoxEditItem>
<dxe:ComboBoxEditItem>BBB</dxe:ComboBoxEditItem>
<dxe:ComboBoxEditItem>CCC</dxe:ComboBoxEditItem>
</dxe:ComboBoxEditSettings.Items>
</dxe:ComboBoxEditSettings>
</dxb:BarEditItem.EditSettings>
</dxb:BarEditItem>
You can also set a ComboBoxEdit.SelectedIndex property from codebehind if you catch the Loaded event:
<dxb:BarEditItem.EditStyle>
<Style TargetType="dxe:ComboBoxEdit">
<EventSetter Event="Loaded" Handler="ComboBoxEdit_Loaded"/>
</Style>
</dxb:BarEditItem.EditStyle>
//...
void ComboBoxEdit_Loaded(object sender, RoutedEventArgs e) {
((ComboBoxEdit)sender).SelectedIndex = 1;
}
Related
I am adding columns to my ListView programmaticaly with this line of code:
gridView.Columns.Add(New GridViewColumn With {.Header = myWorksheet.Cells(1, myVar).Value, .DisplayMemberBinding = New Binding(myWorksheet.Cells(1, myVar).Value)})
What I want to do is set the HitTest to False so the user cannot resize the columns that were added, I tried doing this in my XAML but it did not work:
<GridView.ColumnHeaderContainerStyle>
<Style BasedOn="{StaticResource {x:Type GridViewColumnHeader}}" TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="IsHitTestVisible" Value="False"/>
</Style>
</GridView.ColumnHeaderContainerStyle>
This probably requires a solution in VB.Net because the XAML code does not apply to columns created programmaticaly?
Added C# tag because I found out it can be converted to VB.Net.
XAML style is applied to all columns added in XAML and from code behind. If you want to set IsHitTestVisible not for all, but only for some column's header, then it will be tricky.
I don't know elegant solution for it. So far I know there is no way to get easy GridViewColumnHeader object, which will be styled.
My offer would be to inject a control instead of setting header text, e.g. TextBlock, which will iterate through parents and set GridViewColumnHeader.IsHitTestVisible to false.
public class TextBlockNoHit<ParentHitTestVisibleType> : TextBlock where ParentHitTestVisibleType: UIElement
{
public bool lsParentHitTestVisible { get; set; }
public TextBlockNoHit()
{
Loaded += TextBlockNoHit_Loaded;
}
private void TextBlockNoHit_Loaded(object sender, RoutedEventArgs e)
{
Loaded -= TextBlockNoHit_Loaded;
DependencyObject dpo = this;
while(dpo!=null)
{
dpo = VisualTreeHelper.GetParent(dpo);
if(dpo is ParentHitTestVisibleType gvch)
{
gvch.IsHitTestVisible = lsParentHitTestVisible;
}
}
}
}
Using then:
var col = new GridViewColumn() { Header = new TextBlockNoHit<GridViewColumnHeader>() { Text = "myWorksheet.Cells...", IsHitTestVisible = false, lsParentHitTestVisible = false}, DisplayMemberBinding = new Binding("myWorksheet.Cells...") };
I can's set PlacementTarget for ContextMenu. It is always opened (via Shift+F10) in the center of listbox.
I tried:
private void listBox_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
if (e.KeyboardDevice.Modifiers == ModifierKeys.Shift &&
(e.Key == Key.F10 || e.SystemKey == Key.F10)){
var listBox = sender as System.Windows.Controls.ListBox;
listBox.ContextMenu.PlacementTarget = listBox.ItemContainerGenerator.ContainerFromItem(listBox.SelectedItem) as ListBoxItem;
}
}
and
private void listBox_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
var listBox = sender as System.Windows.Controls.ListBox;
listBox.ContextMenu.PlacementTarget = listBox.ItemContainerGenerator.ContainerFromItem(listBox.SelectedItem) as ListBoxItem;
}
But it still doesn't work as expected. (I expect it is shown in the center of selected itemlistbox)
Any suggestions?
I've just tried your code. The problem is you cannot change the PlacementTarget of the the ContextMenu once it is set to the ListBox. That means the ListBox is always set as PlacementTarget of the ContextMenu. I understand that that ContextMenu is in fact used for the selected item. So why not set it for each item? Then it works expectedly. Try this:
<ListBox ItemsSource="some_source_here"/>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="ContextMenu">
<Setter.Value>
<!-- your ContextMenu here -->
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
There is not any code behind involved here. Just change your XAML like above.
We figured out yesterday how to get a listbox's contents to switch between different panels I had stacked on top of each other. I'm attempting to do the same thing in WPF this time, obviously the syntax is different. The code worked 100% correctly in the windows form. I've tried a few different ways to try to get the now "grids" to show, but to no avail.
Thanks in advance!
Current code 'attempt'. I'm just demonstrating a couple ways I've attempted to change the code there in that first "case".
private void listBox1_SelectedIndexChanged(object sender, SelectionChangedEventArgs e)
{
// set the listboxselected item to a string variable
string curItem = listBox1.SelectedItem.ToString();
curItem = listBox1.SelectedItem.ToString();
// variable changes depening on mouse click, sets to whichever string value is selected
switch (curItem)
{
case "General":
gridGeneral.Visibility == true;
gridRightClick.Visibility = Visibility.Visible;
gridSnaps.Visibility = Visibility.Hidden;
break;
case "E-Snaps":
gridGeneral.Visibility = Visibility.Hidden;
gridRightClick.Visibility = Visibility.Hidden;
gridSnaps.Visibility = Visibility.Visible;
break;
case "Mouse":
gridGeneral.Visibility = Visibility.Hidden;
gridRightClick.Visibility = Visibility.Visible;
gridSnaps.Visibility = Visibility.Hidden;
break;
}
Here is the code that works in a windows form
private void listBox1_SelectedIndexChanged(object sender, System.EventArgs e)
{
// set the listboxselected item to a string variable
string curItem = listBox1.SelectedItem.ToString();
curItem = listBox1.SelectedItem.ToString();
// variable changes depening on mouse click, sets to whichever string value is selected
switch(curItem)
{
case "General" :
panel1.Visible = false;
panel2.Visible = true;
panel3.Visible = false;
panel4.Visible = false;
panel5.Visible = false;
break;
etc etc etc....
You wouldn't do this the same way in WPF that you would in WinForms
In WPF, you'll probably have a single control in WPF where in WinForms you have 3, and the Template that control uses to render will change based on the SelectedItem of your ListBox
Most likely the control definition will look something like this, so that the content of it is bound to the ListBox.SelectedItem:
<ContentControl Content="{Binding ElementName=listBox1, Path=SelectedItem}" />
And you can either use ContentTemplates or DataTemplates to tell WPF how to draw that ContentControl's ContentTemplate.
If the SelectedItem is a custom class, a DataTemplate would probably be easier, however since its a string in your example, a ContentTemplate is probably better.
Here's an example of a style for that ContentControl which changes the ContentTemplate property based on the value of the Content
<Style TargetType="{x:Type ContentControl}">
<!-- // Default Template -->
<Setter Property="ContentTemplate" Value="{StaticResource GeneralTemplate}" />
<!-- // Change template depending on a property -->
<Style.Triggers>
<Trigger Property="Content" Value="ESnaps">
<Setter Property="ContentTemplate" Value="{StaticResource ESnapsTemplate}" />
</Trigger>
<Trigger Property="Content" Value="Mouse">
<Setter Property="ContentTemplate" Value="{StaticResource MouseTemplate}" />
</Trigger>
</Style.Triggers>
</Style>
(I may have the syntax of the exact binding you need wrong here... will probably need some testing)
I'm trying to get the value of the highlighted item of the dropdown list in a ComboBox while the dropdown list is still open.
This is because I want to show a different ToolTip for all the element in the dropdown list based on the highlighted item.
I have found some information here:
http://social.msdn.microsoft.com/Forums/vstudio/en-US/822f85e7-524a-4af2-b09a-c88c94971ac0/identifying-the-highlighted-item-in-a-combobox
but seems to be difficult and with a lot of code behind...
I have also try to use the IsHighlighted property of ComboBoxItem on SelectionChanged... But I give the item selected and not the highlighted one.
I also try to cycling the elements in the ComboBox in the get of property that I bind (with Databinding) to the ToolTip property of ComboBoxItems, using a function like:
foreach (ComboBoxItem comboBoxItem in comboBox.Items)
{
if (comboBoxItem.IsHighlighted == true)
{
//Do something
break;
}
}
But I probably do something wrong... Because comboBoxItem.IsHighlighted it is always false...
Thanks to this resources:
http://social.msdn.microsoft.com/Forums/vstudio/en-US/ce14fc29-d320-4557-abc5-81b042730c48/how-to-get-current-combobox-item-on-which-mouse-overs-in-wpf
I found this solution:
In the WPF:
<ComboBox
Name="ComboBox1">
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<EventSetter Event="MouseMove" Handler="OnMouseMove" />
</Style>
</ComboBox.ItemContainerStyle>
<ComboBoxItem
Content="Test1"></ComboBoxItem>
<ComboBoxItem
Content="Test2"></ComboBoxItem>
</ComboBox>
In the code behind:
private void OnMouseMove(object sender, MouseEventArgs e)
{
ComboBoxItem highlightedComboBoxItem = sender as ComboBoxItem;
// highlightedComboBoxItem is true
}
I want to make it so a double click is required to select an item in a ListBox. This selected item should always be bold. I know the SelectedItem property will no longer reflect the item I am treating as the selected item, so the XAML below that I was previously using to make the selected item bold will no longer work.
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold"/>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
I have looked into how to handle a double click with MVVM and have concluded that it is ok to use code behind and the MouseDoubleClick event.
private void lbProfiles_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
_viewModel.SelectedProfile = ((ListBox)sender.)SelectedItem as MyProfile;
//What should go here?
}
My view model will have a SelectedProfile property that I think will be set in the method above. Is there anyway to bind SelectedProfile in XAML or will it have to be managed in the code behind? Also, what is the best way to make this item bold?
Edit 1:
I ended up tweaking Rachel's answer a little so that on a single click the item is highlighted but not selected. That way the view model can have a SelectedItem property and a HighlightedItem property.
private void ListBoxItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount < 2)
e.Handled = true;
var clickedItem = ((ContentPresenter)e.Source).Content as MyProfile;
if (clickedItem != null)
{
//Let view model know a new item was clicked but not selected.
_modelView.HighlightedProfile = clickedItem;
foreach (var item in lbProfiles.Items)
{
ListBoxItem lbi =
lbProfiles.ItemContainerGenerator.ContainerFromItem(item) as ListBoxItem;
//If item is not displayed on screen it may not have been created yet.
if (lbi != null)
{
if (item == clickedItem)
{
lbi.Background = SystemColors.ControlLightBrush;
}
else
{
lbi.Background = lbProfiles.Background;
}
}
}
}
}
The easiest way to select an item on DoubleClick only is to mark the click event as Handled if the ClickCount is less than 2
This would also allow you to keep your Trigger that sets the text as Bold when it's selected
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<EventSetter Event="PreviewMouseDown" Handler="ListBoxItem_PreviewMouseDown" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
private void ListBoxItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount < 2)
e.Handled = true;
}
Just keep in mind that this disables all single click events on the ListBoxItem. If you want to allow some single-click events, you'll have to adjust the PreviewMouseDown event to not mark specific clicks as Handled.