Is there anyway in Silverlight combobox to specify a value and a text like an html dropdownlist? I only see a content property. I read that I could use the tag property but I am not able to retrieve the value from the code behind when doing...
mycombobox.Tag.toString();
Anyone know of the best way to do this?
Thanks,
Have a custom class that can hold 2 properties to represent the value and text fields of a drop down item. And bind the list of that class as the ItemsSource of the combobox.
you could try
public class CustomComboBoxItem
{
public int Key { get; set; }
public string DisplayText { get; set; }
}
and
public MainPage()
{
InitializeComponent();
myComboboxSource = new List<CustomComboBoxItem>();
myComboboxSource.Add(new CustomComboBoxItem { Key = 1, DisplayText = "First Text" });
myComboboxSource.Add(new CustomComboBoxItem { Key = 2, DisplayText = "Second Text" });
}
public List<CustomComboBoxItem> myComboboxSource { get; set; }
In Xaml,
<ComboBox Name="myCombobox" Height="25" Width="200" ItemsSource="{Binding myComboboxSource, ElementName= mainPage}" SelectedValuePath="Key" DisplayMemberPath="DisplayText"/>
<Button Click="Button_Click" Height="25" Width="100" Content="Get Selected Value"/>
You can test the selected value by using
private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show(Convert.ToString(myCombobox.SelectedValue));
}
Related
I am facing a problem while binding the double click event on Listbox item.
I am using MVVM and Prism. I didn't understand what is wrong here.
View
<ListBox HorizontalAlignment="Center" ItemsSource="{Binding Cities , Source={StaticResource vmC}}" SelectedItem="{Binding SelectedCity , Source={StaticResource vmC}}" Width="100" Height="200">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}">
<TextBlock.InputBindings>
<MouseBinding Gesture="LeftDoubleClick"
Command="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.ItemSelectedCommand}"/>
</TextBlock.InputBindings>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
ViewModel
public class CityViewModel : ViewModelBase
{
public DelegateCommand ItemSelectedCommand { get; private set; }
public string SelectedCity { get; set; }
public List<string> Cities { get; private set; }
public CityViewModel()
{
ItemSelectedCommand = new DelegateCommand(OnItemSelected);
Cities = new List<string>() { "Bangalore", "New York", "Sydney", "London", "Washington" };
}
private void OnItemSelected()
{
var city = SelectedCity;
}
}
MouseBinding is not part of the visual tree. This means, you cannot use Binding.RelativeSource as there is no tree to traverse.
Instead you must bind to the current DataContext, which is the item's data model. To accomplish this, you would have tzo introduce a model class e.g. City that exposes a Name and ItemSelectedCommand property.
If moving the command to the item model doesn't make sense in your scenario, you should use a RoutedCommand and handle it e.g., in the parent Window. InputBinding is primarily intended to be used in the view only and therefore encourages the use of RoutedCommand.
In your case, it seems you are only interested in notifying the CityViewModel that the selection has changed. In this case simply call OnItemSelected from the SelectedCity property set():
public class CityViewModel : ViewModelBase
{
private string selectedCity;
public string SelectedCity
{
get => selectedCity;
set
{
selectedCity = value;
OnItemSelected();
}
}
public List<string> Cities { get; private set; }
public CityViewModel()
{
...
}
private void OnItemSelected()
{
var city = SelectedCity;
}
}
I need a combobox to list the items from a List with two fields :
AcctTypeID - This is an int (0 - 20).
AcctTypeName - This is a string -- ex. "Accounts Payable" (the cooresponding AcctTypeID is say 10 for Accounts Payable).
I need the ComboBox to show the AcctTypeName but send the AcctTypeID to the underlying field.
I promise I have spent hours seraching for this and trying every idea I can think of or find.
Use this XAML and set or bind the ItemsSource of the ComboBox to an IEnumerable<T> where T is your class with the AcctTypeName and AcctTypeID properties:
<ComboBox x:Name="cmb" DisplayMemberPath="AcctTypeName" SelectedValuePath="AcctTypeID" />
You get the selected value using the SelectedValue property:
int acctTypeID = (int)cmb.SelectedValue;
It is impossible to give an exact answer to your question without some additional explanations.
For example, if you are using MVVM, then your code should be implemented like this:
public class AcctTypeDto
{
public int AcctTypeId { get; set; }
public string AcctTypeName { get; set; }
}
public class AcctTypesViewModel
{
public ObservableCollection<AcctTypeDto> AcctTypes { get; }
= new ObservableCollection<AcctTypeDto>()
{
new AcctTypeDto(){AcctTypeId=123, AcctTypeName="Teen"},
new AcctTypeDto(){AcctTypeId=456, AcctTypeName="Five"},
new AcctTypeDto(){AcctTypeId=789, AcctTypeName="Seven"}
};
private RelayCommand _sendIdCommand;
public RelayCommand SendIdCommand => _sendIdCommand
?? (_sendIdCommand = new RelayCommand<int>(SendIdExecute));
private static void SendIdExecute(int parameter)
{
MessageBox.Show($"Id={parameter}");
}
private RelayCommand _sendAccCommand;
public RelayCommand SendAccCommand => _sendAccCommand
?? (_sendAccCommand = new RelayCommand<AcctTypeDto>(SendAccExecute));
private static void SendAccExecute(AcctTypeDto parameter)
{
MessageBox.Show($"Id={parameter.AcctTypeId}; Name={parameter.AcctTypeName}");
}
}
<FrameworkElement.DataContext>
<local:AcctTypesViewModel/>
</FrameworkElement.DataContext>
<UniformGrid Columns="1">
<ComboBox x:Name="comboBox" VerticalAlignment="Top" ItemsSource="{Binding AcctTypes}"
DisplayMemberPath="AcctTypeName"
SelectedValuePath="AcctTypeId"/>
<Button Content="Send Id" VerticalAlignment="Center"
Command="{Binding SendIdCommand}"
CommandParameter="{Binding SelectedValue, ElementName=comboBox}"/>
<Button Content="Send AcctType" VerticalAlignment="Center"
Command="{Binding SendAccCommand}"
CommandParameter="{Binding SelectedItem, ElementName=comboBox}"/>
</UniformGrid>
RelayCommand and RelayCommand<T> classes used.
I'm trying to make use of EntityFramework and WPF data binding for the first time.
I have some ListBox. I have set ItemsSource to SomeDbContext.SomeEntity.ToList(); programatically and I have set my binding like this:
<ListBox Name="listbox" Margin="4" SelectedValuePath="Address" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Label Content="{Binding Id}"></Label>
<Label Content="{Binding Address}"></Label>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Click="ButtonTest_Click">Open</Button>
I'm adding new item to my DbSet and I expected that my list will refresh after SomeDbContext.SaveChanges(); method call, but it didn't.
My Window code behind:
DatabaseContext _dbContext = new DatabaseContext();
public MainWindow()
{
InitializeComponent();
lb.ItemsSource = _dbContext.Addresses.ToList();
// I have tried to set source to _dbContext
}
private void ButtonTest_Click(object sender, RoutedEventArgs e)
{
_dbContext.Addresses.Add(new Adresses() { Address = "192.168.1.2:502" });
_dbContext.SaveChanges();
}
Here is my Entity:
public class Adresses
{
public int Id { get; set; }
public string Address { get; set; }
}
My DbContext:
public class DatabaseContext : DbContext
{
public DbSet<Adresses> Addresses { get; set; }
}
What I am doing wrong?
I guess that my approach is wrong, because I'm creating new object when I'm setting ItemsSource to _dbContext.Addresses.ToList();, but I have no idea how to bind directly to my DbSet (or is it possible).
I have list of type field that can represent a hierarchy: List MyFields
public class Field
{
public Field(string name, string value)
{
this.Name = name;
this.Value = value;
}
public string Name { get; set; }
public string Value { get; set; }
public IList<Field> SubFields { get; set; }
}
How can i bind MyFields to a TreeView?
EDIT:
I forgot, i want to eg. show the value in a message box when clicking on the item.
Set the TreeViews ItemsSource to the Property you want to bind with.
You can create a HierarchicalDataTemplate which should be placed in the resources of your TreeView or at an higher level, make sure to set the DataType to your class to make it apply.
Something like this for example:
<HierarchicalDataTemplate DataType="{x:Type data:Field}"
ItemsSource="{Binding SubFields}">
<ContentControl MouseDoubleClick="TreeViewItem_MouseDoubleClick">
<TextBlock Text="{Binding Name}"/>
</ContentControl>
</HierarchicalDataTemplate>
private void TreeViewItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
Field field = (sender as FrameworkElement).DataContext as Field;
MessageBox.Show(field.Value.ToString());
}
You also need a root-elements list to which you can bind the ItemsSource of the TreeView itself.
How would someone go about adding check boxes to only the children of a tree view in XAML? My goal is to have a tree view where the parent is just a text block and all the children are check boxes but only one child can be checked at a time. I have no problem making the whole the tree view check boxes but I am not sure how to get what I really want Any suggestions?
Thanks.
Why don't you just do it in code? Like this:
TreeViewItem newItem = new TreeViewItem()
{
Header = "One"
};
treeViewObjects.Items.Add(newItem);
TreeViewItem newItem1 = new TreeViewItem()
{
Header = new CheckBox()
{
Content = "Two"
}
};
newItem.Items.Add(newItem1);
Try this Working with Checkboxes in the WPF TreeView.
The easiest way to do this is to shape your data so that the tree view can represent it in the way you've described. Here is an example of a minimal data structure that corresponds to your type of tree:
public class CheckedList
{
public string Title { get; set; }
public ObservableCollection<CheckedItem> Items { get; private set; }
public CheckedList()
{
Items = new ObservableCollection<CheckedItem>();
//DEBUG: Test data
Title = "Test Title";
Items.Add(new CheckedItem("Item 1", true));
Items.Add(new CheckedItem("Item 2", false));
}
}
public class CheckedItem : DependencyObject
{
public static readonly DependencyProperty StateProperty =
DependencyProperty.Register("StateProperty", typeof(bool), typeof(CheckedItem), new UIPropertyMetadata(false));
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("TextProperty", typeof (string), typeof (CheckedItem), new UIPropertyMetadata(string.Empty));
public bool State
{
get { return (bool)GetValue(StateProperty); }
set { SetValue(StateProperty, value); }
}
public string Text
{
get { return (string) GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public CheckedItem(string text, bool state)
{
Text = text;
State = state;
}
}
Here is XAML and code-behind for a window and tree view with data templates to represent the data as text headers with check box items:
<Window x:Class="TestApp.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestApp"
Title="Window1" Height="300" Width="300" Loaded="Window_Loaded">
<Window.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:CheckedList}" ItemsSource="{Binding Items}">
<TextBlock Text="{Binding Title}" />
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type local:CheckedItem}">
<CheckBox Content="{Binding Text}" IsChecked="{Binding State, Mode=TwoWay}"></CheckBox>
</DataTemplate>
</Window.Resources>
<Grid>
<TreeView x:Name="ExampleTree"></TreeView>
</Grid>
The code-behind:
public partial class Window1 : Window
{
ObservableCollection<CheckedList> _lists = new ObservableCollection<CheckedList>();
public Window1()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
//DEBUG: Test data
_lists.Add(new CheckedList());
_lists.Add(new CheckedList());
ExampleTree.ItemsSource = _lists;
}
}
Using ObservableCollection and DependencyObject allows the tree and data structure to stay in sync. As the user clicks on items in the tree, you should be able to look at your lists and see the modifications. Alternately, if you modify the data, it should be reflected in the tree.