添加/删除控件行 [英] Adding/removing rows of controls

查看:157
本文介绍了添加/删除控件行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个面板,我的想法是让它包含一个包含两个文本框的堆栈面板。当用户在左边框中输入内容时,应该在右侧生成一些内容,如下所示。

 < StackPanel方向= 水平 > 
< TextBox Name =LeftyLostFocus =FillMyBuddy/>
< TextBox Name =RightyLostFocus =FillMyBuddy/>
< / StackPanel>

但是,我想添加一个选项来添加/删除行,因为我不希望为了限制自己的数量,我对两点的方法有点不确定。


  1. 操纵DOM(嗯,它是XAML / WPF,但你看到我的目标)。

  2. 事件处理。

是否以编程方式影响标记 - 窗口的结构?或者在运行期间添加/删除面板可以吗?



如果我想要 Lefty 号码3,建议的方法是什么?更改 3号中的内容比检查发件人和从父母拉他的兄弟姐妹更整洁吗?我想为任何行和所有行使用单个事件处理程序(知道操作始终是行内的)。

解决方案

p>您将要跟踪MVVM,并且您的代码隐藏中没有代码(以编程方式影响标记结构)文件。这个概念很简单,当你把握它,所以学习它,然后再开始编写你的代码。简单来说,您将要拥有一个视图模型(实现 INotifyPropertyChanged (INPC))的视图模型(



它保存您的项目集合(将成为模型,或在纯MVVM中查看模型)。在混合型-MVVM中,您可以让您的型号实现INPC。



然后,通过使用命令,您将实现从列表中删除项目的逻辑。您可以传递引用,提高通知,使用事件冒泡等等(这是你的偏好)让项目实际删除。在我的情况下,我刚刚通过一个经理到混合模型,并提到了这一点。当命令被调用(按钮被点击)时,模型调用引用将其从列表中删除。



在你这样做之后,你定义一个 DataTemplate 来定义一个项目应该是一个View。您使用 ItemsControl 显示项目集合,并绑定到其 ItemsSource ,以显示项目集合。将您的 ItemsControl.ItemTemplate 设置为您创建的 DataTemplate ,并将添加到集合中的任何内容绑定到 DataTemplate.DataType 中定义的类型的ItemsSource 将按照您在 DataTemplate



最后,您应该了解MVVM设计, DataContext ,INPC,命令,控件类型和他们的主要属性,例如从 ItemsControl 继承的所有内容都有一个 ItemsSource 属性。



这里是一个工作示例,其中更改原始字符串,将其反转并将其放在只读右侧文本框中:





从这里开始,你有要做的就是将你的控件的属性改变为你喜欢的任何东西,并称之为好。这个例子可能是丑陋的,但是我将它作为一个练习,让你找出WPF控件的其他属性/属性。


I have a panel and my idea is to have it populated by a stack panel containing two text boxes. When the user enters something in the left box, something should be generated in the right one, as follows.

<StackPanel Orientation="Horizontal">
  <TextBox Name="Lefty" LostFocus="FillMyBuddy" />
  <TextBox Name="Righty" LostFocus="FillMyBuddy" />
</StackPanel>

However, I'd like to add an option to add/remove rows and, since I wish not to limit myself to the number of such, I get a bit uncertain regarding the approach on two points.

  1. Manipulating DOM (well, it's XAML/WPF but you see what I'm aiming at).
  2. Event handling.

Is it a big no-no to programmatically affect the mark-up structure of the window? Or is it OK to add/remove panels during run-time?

What would the recommended way to be if I want the Lefty number 3 change stuff in Righty number 3? Anything more neat than checking the sender and pulling its siblings from the parent? I want to use a single event handler for any and all rows (knowing that the operations are always intra-row-wise).

解决方案

You will want to follow MVVM, and have no code in your code-behind (programmatically affect the mark-up structure) files. The concept is easy when you grasp it, so learn it before you start writing your code.

In short, you are going to want to have a view model (something that implements INotifyPropertyChanged (INPC)) which holds your collection of items (which are going to be models, or view models in pure-MVVM). In "hybrid"-MVVM you could just have your models implement INPC.

Then, through the use of commands, you'd implement the logic to remove items from the list that its in. You can pass references, raise notification, using event bubbling, etc. (it's your preference) to have the item actually removed. In my case, I just passed a "manager" to the hybrid-model and held a reference to that. When the command is called (button is clicked), the model calls for the reference to remove itself from the list.

After you do that you define a DataTemplate to define what an "item" should look like one the View. You use a ItemsControl to show a collection of items, and bind to its ItemsSource so the collection of items are shown. Set your ItemsControl.ItemTemplate to the DataTemplate you created, and anything added to the collection bound to ItemsSource of the type defined in DataTemplate.DataType will render as you specify in the DataTemplate.

At the end of the day, you should learn about MVVM design, DataContext, INPC, Commands, Control types and their "main" properties, e.g. everything that inherits from ItemsControl has an ItemsSource property.

Here is a working example, where changing the original string, will reverse it and put it in the read-only right side text box:

MainWindow.xaml.cs (code-behind)

public partial class MainWindow : Window
{
    StructureVm _struct = new StructureVm("Test");

    public MainWindow()
    {
        InitializeComponent();

        DataContext = _struct;
    }
}

MainWindow.xaml (View)

<Window x:Class="DataTemplateWithCommands.MainWindow"
        xmlns:local="clr-namespace:DataTemplateWithCommands"
        Title="MainWindow" Height="350" Width="525" Background="Orange">
    <Window.Resources>
        <DataTemplate DataType="{x:Type local:Model}"
                      x:Key="VmItem">
            <StackPanel Orientation="Horizontal">
                <TextBox Text="{Binding Original, UpdateSourceTrigger=PropertyChanged}" />
                <TextBox Text="{Binding Encoded}"
                         IsReadOnly="True" />
                <Button Content="X"
                        Command="{Binding RemoveMeCommand}" />
            </StackPanel>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <ItemsControl ItemsSource="{Binding Items}"
                      ItemTemplate="{StaticResource VmItem}">
        </ItemsControl>
    </Grid>
</Window>

Interface (helpful for Dependency Injection)

public interface IStructureManager
{
    bool RemoveItem(Model itemToRemove);
}

ViewModel

public class StructureVm : IStructureManager
{
    private readonly ObservableCollection<Model> _items;
    private readonly string _title;

    public StructureVm(string title)
    {
        _title = title;
        _items = new ObservableCollection<Model>
            {
                new Model(this, "12"),
                new Model(this, "23"),
                new Model(this, "34"),
                new Model(this, "45"),
                new Model(this, "56"),
                new Model(this, "67"),
                new Model(this, "78"),
                new Model(this, "89"),
            };
    }}

    public ObservableCollection<Model> Items
    {
        get
        {
            return _items;
        }
    }

    public string Title
    {
        get
        {
            return _title;
        }
    }

    public bool RemoveItem(Model itemToRemove)
    {
        return _items.Remove(itemToRemove);
    }
}

Model (not pure-MVVM, pure MVVM models don't implement INPC, and don't have Command in them)

public class Model : INotifyPropertyChanged
{
    private readonly RelayCommand _removeMe;
    private string _original;
    private string _encoded;
    private readonly IStructureManager _manager;
    public string Original
    {
        get
        {
            return _original;
        }
        set
        {
            _original = value;
            Encoded = ReverseString(_original);
            NotifyPropertyChanged();
        }
    }

    public string Encoded
    {
        get
        {
            return _encoded;
        }
        set
        {
            _encoded = value;
            NotifyPropertyChanged();
        }
    }

    public ICommand RemoveMeCommand
    {
        get
        {
            return _removeMe;
        }
    }

    public Model(IStructureManager manager, string original)
    {
        Original = original;
        _manager = manager;
        _removeMe = new RelayCommand(param => RemoveMe(), param => CanRemoveMe);
    }

    private void RemoveMe()
    {
        _manager.RemoveItem(this);
    }

    private bool CanRemoveMe
    {
        get
        {
            //Logic to enable/disable button
            return true;
        }
    }

    private string ReverseString(string s)
    {
        char[] arr = s.ToCharArray();
        Array.Reverse(arr);
        return new string(arr);
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged([CallerMemberName]string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

RelayCommand implementation

From here on out all you have to do is change the attributes of your controls to whatever you're happy with and call it good. The example might be ugly, but I'm leaving it as an exercise for you to figure out other properties/attributes of WPF controls.

这篇关于添加/删除控件行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆