WPF combobox databinding both to custom objects and to datatable.showing System.Data.DataRowView in dropdown list items
I've posted a similar problem here and wasn't able to successfully implement the solution suggested to me as it wasn't working.I've found a way round and wanted to improve it by binding the combobox to a custom objects to enable data validation.here is the xaml for this one
<Window xmlns:data="clr-namespace:Myproject">
<Window.Resources>
<data:UserLogin x:Key="user"></data:UserLogin>
<DataTemplate x:Key="comboTemplate">
<TextBlock Text="{Binding Path=username}" />
</DataTemplate>
</Window.Resources>
<ComboBox Margin="18,121,24,0" Name="cmbEmail" Tag="email" TabIndex="1" ToolTip="enter the email you signed up with here" IsEditable="True" IsSynchronizedWithCurrentItem="True" ItemTemplate="{StaticResource comboTemplate}" ItemsSource="{Binding}" Height="23" VerticalAlignment="Top" Style="{DynamicResource cmbBoxerrors}">
<ComboBox.Text>
<Binding Path="Loginname" Source="{StaticResource user}" ValidatesOnDataErrors="True" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<ExceptionValidationRule/>
</Binding.ValidationRules>
</Binding>
</ComboBox.Text>
</ComboBox>
</Window>
and the xaml.cs is
if (con != null)
{
if (con.State == ConnectionState.Closed)
con.Open();
SqlCeCommand cmdusers = new SqlCeCommand("select * from users order by id", con);
SqlCeDataAdapter da = new SqlCeDataAdapter(cmdusers);
userdt = new DataTable("users");
da.Fill(userdt);
cmbEmail.DataContext = userdt;
}
and the Us开发者_高级运维erLogin Class is
class UserLogin :IDataErrorInfo
{
private string _loginname = "";
private string _password;
public string this[string columnName]
{
get
{
string result = null;
if(columnName == "Loginname")
{
if(string.IsNullOrEmpty(this._loginname))
{
result = "Login Name cannot be Empty";
}
}
if (columnName == "Loginname")
{
if(!Util.ValidateRegexPatern(Properties.Resources.emailRegex,this._loginname))
{
result = "MalFormed Email address. Please write a correct email addess";
}
}
return result;
}
}
public string Error
{
get { return null; }
}
public string Password
{
get { return _password; }
set { _password = value; }
}
public string Loginname
{
get { return _loginname; }
set { _loginname = value; }
}
}
the problem is when i use ItemTemplate
the selected item shows System.Data.DataRowView
but dropdown list items show correctly and when i swap the ItemTemplate
with DisplayMemberPath
it's the opposite behavior as in selected items is correct and dropdown list items show System.Data.DataRowView
.using them both throws an exception as i can't use them both selected and dropdown list items show correctly.
I don't really know what i'm not doing correctly.Can anyone shed some light on this i'll be verry thankfull.Thanks for reading this
It goes like this: you set the data context of the ComboBox to an instance of type DataTable. Then you set the ItemsSource to {Binding} which means each item in the ComboBox will bind to a DataRow (which doesn't have either loginname, nor username as properties). And here the binding stops working. There's no implicit way to convert from a DataRow to a UserLogin.
You ca either implement a converter to do the conversion or convert the rows to UserLogin one by one and set the DataContext of the ComboBox to the list of UserLogin (or an ObservableCollection if you need more advanced functionality).
In either case drop the <ComboBox.Text> ... </ComboBox.Text>
part.
Hope this helps you...
精彩评论