[英]Bind combo box within listbox WPF
我是WPF的新手,我試圖填充列表框中的combox控件
XAML:
<Window.Resources>
<DataTemplate x:Key="UserTemplate" >
<StackPanel Orientation="Horizontal" >
<ComboBox Name="rule" ItemsSource="{Binding}" DisplayMemberPath="DataContext.RuleType" Width="85" Height="20"
SelectedValuePath="DataContext.RuleType" SelectedValue="{Binding Path=DataContext.RuleType}"/>
<TextBlock Text="{Binding Path= Name1}" Width="85" Margin="5,5,5,5"></TextBlock>
<Button Content="Delete" Click="cmdDeleteUser_Clicked" Margin="5,5,5,5" />
<Button Content="Add" Click="cmdAddUser_Clicked" Margin="5,5,5,5" />
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<ListBox Name="lbUsers" ItemsSource="{Binding }" ItemTemplate="{StaticResource UserTemplate}"/>
</Grid>
代碼如下:
public ObservableCollection<User> Users;
ObservableCollection<Listdata> listeddata;
ObservableCollection<Records> Record;
public MainWindow()
{
InitializeComponent();
Users = new ObservableCollection<User>() {
new User() { Name = "", Age = "" },
};
DataboundListbox.Records record = new Records();
RuleType = record.record_Rule();
lbUsers.DataContext = Users;
}
private string _Name;
public string Name1
{
get { return _Name; }
set
{
if (value != _Name)
{
_Name = "John";
NotifyPropertyChanged("Name");
}
}
}
private List<string> _RuleType;
public List<string> RuleType
{
get { return _RuleType; }
set
{
if (value != _RuleType)
{
_RuleType = value;
NotifyPropertyChanged("RuleType");
}
}
}
private void NotifyPropertyChanged(string info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
private void cmdDeleteUser_Clicked(object sender, RoutedEventArgs e)
{
Button cmd = (Button)sender;
if (cmd.DataContext is User)
{
User deleteme = (User)cmd.DataContext;
Users.Remove(deleteme);
}
}
private void cmdAddUser_Clicked(object sender, RoutedEventArgs e)
{
Button cmd = (Button)sender;
if (cmd.DataContext is User)
{
var addedUser = new User() { Name = "", Age = "" };
Users.Add(addedUser);
}
}
private List<string> _prp;
public List<string> prp
{
get { return _prp; }
set
{
if (value != _prp)
{
_RuleType = value;
NotifyPropertyChanged("prp");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
問題:
主要問題在於以下兩行:
{Binding Path=DataContext.RuleType}
{Binding Path= Name1}
由於您已經聲明了dataContext,因此DataContext.RuleType將使編譯器搜索yourdatacontext.DataContext.RuleType ,這顯然不是您想要的。
lbUsers.DataContext = Users;
解
在WPF中,強烈建議使用MVVM (模型視圖viewmodel)模式。 它的主要功能之一是將GUI邏輯與Business Logic分開,從而使代碼更整潔,更易於維護。
步驟1:建立ViewModel
public class UserViewModel:INotifyPropertyChanged
{
private string name;
private string age;
private string rule;
private List<string> ruleType;
public String Name
{
get { return name; }
set { name = value; NotifyPropertyChanged("Name"); }
}
public String Age
{
get { return age; }
set { age = value; NotifyPropertyChanged("Age"); }
}
public String Rule
{
get { return rule; }
set { rule = value; NotifyPropertyChanged("Rule"); }
}
public List<string> RuleType
{
get { return ruleType; }
set { ruleType = value; NotifyPropertyChanged("RuleType"); }
}
public UserViewModel()
{
name = "name";
age = "";
ruleType = new List<string>();
}
#region NotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
#endregion
}
}
第2步:將數據上下文鏈接到視圖模型
public MainWindow()
{
InitializeComponent();
Users = new ObservableCollection<UserViewModel>();
//setup your data here
//example:
UserViewModel userViewModel = new UserViewModel();
//populate your combobox here
userViewModel.RuleType.Add("rule1")
userViewModel.RuleType.Add("rule2");
userViewModel.RuleType.Add("rule3");
Users.Add(new UserViewModel());
lbUsers.DataContext = Users ;
}
步驟3:更新您的XAML
<Window.Resources>
<DataTemplate x:Key="UserTemplate" >
<StackPanel Orientation="Horizontal" >
<ComboBox Name="rule" ItemsSource="{Binding RuleType}" Width="85" Height="20"
SelectedValue="{Binding Rule}"/>
<TextBlock Text="{Binding Path= Name}" Width="85" Margin="5,5,5,5"></TextBlock>
<Button Content="Delete" Click="cmdDeleteUser_Clicked" Margin="5,5,5,5" />
<Button Content="Add" Click="cmdAddUser_Clicked" Margin="5,5,5,5" />
</StackPanel>
</DataTemplate>
</Window.Resources>
當我打字時,bahman已經發布了一個非常詳細的答案。所以我在這里停了下來。 如果您需要我的任何解釋或解決方案,只需詢問即可。
將來,如果您懷疑有關綁定的任何錯誤,則可以搜索輸出窗口。 如果您看到輸出窗口,則可能會發現
System.Windows.Data Error: 40 : BindingExpression path error: 'DataContext' property not found on 'object' ''User' (HashCode=9080996)'. BindingExpression:Path=DataContext.RuleType; DataItem='User' (HashCode=9080996); target element is 'ComboBox' (Name=''); target property is 'SelectedValue' (type 'Object')
System.Windows.Data Error: 40 : BindingExpression path error: 'Name1' property not found on 'object' ''User' (HashCode=9080996)'. BindingExpression:Path=Name1; DataItem='User' (HashCode=9080996); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')
在我可以回答您的問題之前,應該清除一些混亂。
如果User
已經有一個名為Name
的成員,那么父類中的Name1
是做什么用的?
如果RuleType
是一個列表,為什么將其設置為ComboBox
的SelectedValue
,而不應該是ComboBox.itemsSource
嗎? 如果應該,那么在哪里定義該屬性以保留ComboBox.SelectedValue
?
為什么UserTemplate
有一個Add
按鈕? Delete
按鈕可以,但是我認為Add
屬於ListBox
之外。
如果我正確理解您的問題,那么這就是我能想到的解決方案。
Fisrt : User
需要一個類似於SelectedRule
的屬性來保留Combobox.SelectedItem
:
public class User : INotifyPropertyChanged
{
// implementation of INotifyPropertyChanged
string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
NotifyPropertyChanged("Name");
}
}
int _age;
public int Age
{
get
{
return _age;
}
set
{
_age = value;
NotifyPropertyChanged("Age");
}
}
string _selectedRule;
public string SelectedRule
{
get
{
return _selectedRule;
}
set
{
_selectedRule = value;
NotifyPropertyChanged("SelectedRule");
}
}
}
第二 :您的DataTemplate
應該像這樣更改:
<Window.Resources>
<DataTemplate x:Key="UserTemplate" >
<StackPanel Orientation="Horizontal" >
<ComboBox Name="rule" ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=RuleType}" DisplayMemberPath="." Width="85" Height="20"
SelectedItem="{Binding SelectedRule}"/>
<TextBlock Text="{Binding Path= Name}" Width="85" Margin="5,5,5,5"></TextBlock>
<Button Content="Delete" Click="cmdDeleteUser_Clicked" Margin="5,5,5,5" />
</StackPanel>
</DataTemplate>
</Window.Resources>
最后 , ListBox
部分更改如下:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListBox Grid.Row="0" Name="lbUsers" ItemsSource="{Binding}" ItemTemplate="{StaticResource UserTemplate}"/>
<Button Grid.Row="1" Content="Add" Click="cmdAddUser_Clicked" Margin="5,5,5,5" />
</Grid>
如果要像上面的代碼一樣顯示“ Add
按鈕,則應從cmdAddUser_Clicked
方法中刪除if (cmd.DataContext is User)
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.