2 个关于选项卡和组合框的 WPF(Windows 演示基础)快速问题

发布于 2024-08-22 08:13:51 字数 601 浏览 4 评论 0原文

我是一名非常新手的 WPF 程序员,因此在一些简单的任务中需要帮助。

1-如图所示,我想要 (+) 选项卡(它是现在使用 TabItem 创建的选项卡,还是应该是按钮或其他东西?:-/)来创建一个左侧的选项卡,例如 (A1),再次按下,应该创建(A2),有点像选项卡式浏览器......如果可能的话,按下(-)会删除用户提示中选定的选项卡。

替代文本 http://img191.imageshack.us/img191/4532/tabn.png< /a>

2-我想要,用户在文本框中输入文本,内容用逗号或分号分隔,并且该内容在按钮按下/单击时添加到 COMBOBOX,我猜,它需要某种数据绑定?不确定,..这样,到最后,文本框中的内容将成为组合框中的列表(按下按钮时)........................ 如果可能,在文本框中选择文本时,单击按钮(选择将文本框内容添加到组合框的相同或不同按钮),它会从文本框和组合框中删除相同的内容。

请帮忙,我正在学习 WPF,但需要紧急帮助,但以我目前的知识无法解决。谢谢。

I am a very novice WPF programmer, so need help in some simple tasks.

1- As the image shows, I want the (+) tab(it's a tab created with TabItem as of now or should it be button or something else? :-/) to create a tab left to it, say (A1), pressing again, should create (A2), sort of like in tabbed browsers......... And if possible, pressing (-) deletes the selected tab on user prompt.

alt text http://img191.imageshack.us/img191/4532/tabn.png

2- I want, that user enters text in the textbox, with content separated by comma, or semicolon and that content is added to a COMBOBOX on Button press/click, I guess, it requires some sort of Databinding? Not sure,.. Such that, by the end of it, content from textbox, becomes list within ComboBox (on Button press) ....................
And if possible, the text when selected in text box, on button click(same or different button which was chosen to add textbox content to combobox), it deletes the same from textbox and combobox .

Please help, I am learning WPF, but need this urgent help, which I cannot solve with my current knowledge of it. Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

柏林苍穹下 2024-08-29 08:13:51

数据绑定和 MVVM 使一切变得更加容易。一开始比较困难,但最终会容易得多。

创建两个类,ItemItemCollection,它们都实现 INotifyPropertyChangedItem 应公开字符串 Text 属性,而 ItemCollection 应公开 ObservableCollection Items< /code> 属性和 Item SelectedItem 属性。

ItemCollection 类的构造函数使用测试数据填充 Items 并设置 SelectedItem

在您真正开始实现选项卡控件之前,这似乎需要做很多事情,但是相信我,您会喜欢结果的。 TabControl 的 XAML 将如下所示:

<TabControl
    ItemsSource="{Binding Items}"
    SelectedItem="{Binding SelectedItem}">
    <TabControl.DataContext>
        <local:ItemsCollection/>
    </TabControl.DataContext>
    <TabControl.Resources>
        <DataTemplate DataType="{x:Type local:Item}">
            <TextBlock Background="AliceBlue" Text="{Binding Text}"/>
        </DataTemplate>
    </TabControl.Resources>
    <TabControl.ItemContainerStyle>
        <Style TargetType="{x:Type TabItem}">
            <Style.Setters>
                <Setter Property="Header" Value="{Binding Text}"/>
            </Style.Setters>
        </Style>
    </TabControl.ItemContainerStyle>
</TabControl>

让我们了解它的作用。它创建一个 TabControl。它创建一个 ItemsCollection 对象并将其设置为 TabControlDataContext。您已将 ItemSource 绑定到 Items,因此 TabControl 将为每个项目创建一个 TabItem。它将把 ItemContainerStyle 应用于每个 TabItem,从而将其 Header 属性设置为 Item文本 属性。

当控件呈现选项卡的内容时,它会查找正在呈现的项目,搜索资源以查找 DataType 与该项目匹配的 DataTemplate,并使用该模板。由于我们在 TabControl.Resources 中定义了一个,因此您会再次获得漂亮的蓝色背景和 Text 属性。

这似乎需要经历很多事情。但现在您不必编写任何操作 UI 的代码;您只需编写操作 ItemsCollection 的代码,UI 就会自行处理。

现在让我们来添加新选项卡。我们要做的是将一个新项目添加到控件中,当它被选中时,将一个新项目添加到 Items 集合中。

创建一个新类,名为 ControlItem。让它从 Item 派生。修改 ItemsCollection 构造函数,使其添加的最后一项是 ControlItem,而不是 Item。并将该项目的 Text 属性设置为“+”。

将此方法添加到 ItemsCollection

public Item AddItem()
{
    Item newItem = new Item {Text = "New item"};
    Items.Insert(Items.Count-1, newItem);
    return newItem;
}

现在添加到窗口的代码隐藏,并作为 TabControlSelectionChanged 事件处理程序:

void TabControl_SelectionChanged(object sender, RoutedEventArgs e)
{
    TabControl tc = (TabControl) sender;
    if (tc.SelectedItem is ControlItem)
    {
        ItemsCollection ic = (ItemsCollection) tc.DataContext;
        tc.SelectedItem = ic.AddItem();
    }
}

您可以实现类似的从列表中删除项目的逻辑,但您需要向 ItemsCollection 引入另一个变量来跟踪先前选择的项目,以便您知道要删除哪个项目。

您可以做的另一件事:在 Item 中实现一个 Background 属性,并向绑定 TabItemItemContainerStyle 添加一个 setter > 的 Background 属性。然后,您可以在 ControlItem 中重载该属性,以便您的添加和删除选项卡看起来有所不同。

您还可以为控件项实现不同的子类,并让它们公开您在 SelectionChanged 事件处理程序中调用的方法。这样,事件处理程序就不必知道所单击的控件项正在执行的操作。事实上,如果您将该方法作为 Item 的一部分,并且让它不执行任何操作(除非它被重写),则窗口甚至不需要知道 Item 子类。

简而言之,这就是 MVVM 背后的哲学:将视图绑定到它几乎一无所知的对象。让视图模型对象控制发生的事情,以便视图不必这样做。

Everything's easier with data binding and MVVM. Harder at first, but ultimately lots easier.

Make two classes, Item and ItemCollection, that both implement INotifyPropertyChanged. Item should expose a string Text property, while ItemCollection should expose an ObservableCollection<Item> Items property and an Item SelectedItem property.

Make the ItemCollection class's constructor populate Items with test data and set SelectedItem.

This seems like a lot to do before you actually get around to implementing your tab control, but trust me, you'll like the result. Your XAML for the TabControl will look something like this:

<TabControl
    ItemsSource="{Binding Items}"
    SelectedItem="{Binding SelectedItem}">
    <TabControl.DataContext>
        <local:ItemsCollection/>
    </TabControl.DataContext>
    <TabControl.Resources>
        <DataTemplate DataType="{x:Type local:Item}">
            <TextBlock Background="AliceBlue" Text="{Binding Text}"/>
        </DataTemplate>
    </TabControl.Resources>
    <TabControl.ItemContainerStyle>
        <Style TargetType="{x:Type TabItem}">
            <Style.Setters>
                <Setter Property="Header" Value="{Binding Text}"/>
            </Style.Setters>
        </Style>
    </TabControl.ItemContainerStyle>
</TabControl>

Let's understand what this does. It creates a TabControl. It creates an ItemsCollection object and sets it as the TabControl's DataContext. You've bound ItemSource to Items, so the TabControl will create a TabItem for each item. It will apply the ItemContainerStyle to each TabItem, which sets its Header property to the Item's Text property.

When the control renders the content of a tab, it finds the item it's rendering, searches through the resources to find a DataTemplate whose DataType matches the item, and uses that template. Since we've defined one in TabControl.Resources, you get a nice blue background and the Text property again.

This seems like a lot to go through. But now you don't have to write any code that manipulates the UI; you just write code that manipulates your ItemsCollection, and the UI pretty much takes care of itself.

Now let's take care of adding new tabs. What we're going to do is add a new item to the control that, when it becomes selected, adds a new item to the Items collection.

Create a new class, called, oh, ControlItem. Have it derive from Item. Modify your ItemsCollection constructor so that the last item it adds is a ControlItem, not an Item. And have it set the Text property on that item to "+".

Add this method to ItemsCollection:

public Item AddItem()
{
    Item newItem = new Item {Text = "New item"};
    Items.Insert(Items.Count-1, newItem);
    return newItem;
}

Now add to your window's code-behind, and as the SelectionChanged event handler for your TabControl:

void TabControl_SelectionChanged(object sender, RoutedEventArgs e)
{
    TabControl tc = (TabControl) sender;
    if (tc.SelectedItem is ControlItem)
    {
        ItemsCollection ic = (ItemsCollection) tc.DataContext;
        tc.SelectedItem = ic.AddItem();
    }
}

You can implement similar logic to remove an item from the list, but you'll need to introduce another variable to ItemsCollection to track the previously selected item, so that you can know which item to delete.

Another thing you can do: implement a Background property in Item and add a setter to the ItemContainerStyle that binds the TabItem's Background property to it. Then you can overload that property in ControlItem, so that your add and delete tabs look different.

You can also implement different subclasses for your control items, and have them expose a method that you call in the SelectionChanged event handler. That way, the event handler doesn't have to know anything about what the control item being clicked is doing. In fact, if you make the method part of Item, and have it do nothing unless it's overriden, the window doesn't even need to know that Item has subclasses.

That's the philosophy behind MVVM in a nutshell: Bind the view to objects about which it knows almost nothing. Let the view-model objects control what happens, so that the view doesn't have to.

带刺的爱情 2024-08-29 08:13:51

选项卡控件应该很简单。处理 + 选项卡上的 Click 事件,创建一个新选项卡并将其设为活动选项卡。应该很容易...我必须运行,所以现在无法向您显示代码答案。尝试一下,如有任何问题,请回来。

下一部分我可以提供更多帮助,

<StackPanel>
            <TextBox x:Name="txtOptions" TextChanged="OnTextChanged"></TextBox>
            <ComboBox x:Name="cboSelect" ItemsSource="{Binding Path=Options}"/>
        </StackPanel>

代码隐藏窗口(或您的类)必须实现 INotifyPropertyChanged。还将窗口的 DataContext 属性设置为其自身(例如,在 ctor 中),如 this.DataContext = this;

public partial class Window1 : Window, INotifyPropertyChanged
   {
       string[] _options;
       public string[] Options
       {
           get
           {  return _options;         }
           set
           {
               _options = value;
               if (this.PropertyChanged != null)
                   this.PropertyChanged(this, new PropertyChangedEventArgs("Options"));
           }
       }

文本更改事件处理程序修改代码隐藏上的 Options 属性,并触发以下通知:属性已被修改。组合框会收到通知,因为它是绑定到该属性的数据并且会自我更新。

private void OnTextChanged(object sender, TextChangedEventArgs e)
      {
          this.Options = txtOptions.Text.Split(';');
      }

The tab control should be easy. Handle a Click event on the + tab, create a new tab and make it the active tab. Should be easy... I've gotta run so can't show you the code answer right now. Give it a try and get back with any issues.

The next part I can be a bit more helpful

<StackPanel>
            <TextBox x:Name="txtOptions" TextChanged="OnTextChanged"></TextBox>
            <ComboBox x:Name="cboSelect" ItemsSource="{Binding Path=Options}"/>
        </StackPanel>

the code-behind window (or your class) has to implement INotifyPropertyChanged. Also set the DataContext property of the window to itself (e.g. in the ctor ) like this.DataContext = this;

public partial class Window1 : Window, INotifyPropertyChanged
   {
       string[] _options;
       public string[] Options
       {
           get
           {  return _options;         }
           set
           {
               _options = value;
               if (this.PropertyChanged != null)
                   this.PropertyChanged(this, new PropertyChangedEventArgs("Options"));
           }
       }

The text changed event handler modifies the Options property on the code-behind and fires the notification that the property has been modified. The Combobox is notified since it is data bound to that property and self-updates.

private void OnTextChanged(object sender, TextChangedEventArgs e)
      {
          this.Options = txtOptions.Text.Split(';');
      }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文