簡體   English   中英

在列表框WPF中綁定組合框

[英]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}
  1. 由於您已經聲明了dataContext,因此DataContext.RuleType將使編譯器搜索yourdatacontext.DataContext.RuleType ,這顯然不是您想要的。

     lbUsers.DataContext = Users; 
  2. 您的數據上下文是User類的集合,並且不包含Name1 因此,綁定路徑= Name1將返回“找不到屬性”錯誤

在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')

在我可以回答您的問題之前,應該清除一些混亂。

  1. 如果User已經有一個名為Name的成員,那么父類中的Name1是做什么用的?

  2. 如果RuleType是一個列表,為什么將其設置為ComboBoxSelectedValue ,而不應該是ComboBox.itemsSource嗎? 如果應該,那么在哪里定義該屬性以保留ComboBox.SelectedValue

  3. 為什么UserTemplate有一個Add按鈕? Delete按鈕可以,但是我認為Add屬於ListBox之外。

如果我正確理解您的問題,那么這就是我能想到的解決方案。

FisrtUser需要一個類似於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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM