【问题标题】:Dynamic textbox binding to a list动态文本框绑定到列表
【发布时间】:2017-06-24 19:36:46
【问题描述】:

我对 MVVM 很陌生,但我被数据绑定困住了。我的视图页面上有一个按钮,可以动态创建文本框,但我看不到如何将这些文本框绑定到 ViewModel 中的列表。

在我看来,我有:

<Button x:Name="btWebsite" Grid.ColumnSpan="2" Width="50" Height="50" Click="btWebsite_Click" Margin="23,245,259,202">
        <StackPanel x:Name="pnWebsiteButton" Orientation="Horizontal">
            <Image x:Name="imgWebsite" Source= "Images/webIcon.jpg" Stretch="Fill"  HorizontalAlignment="Left" VerticalAlignment="Top"/>
        </StackPanel>
    </Button>
    <GroupBox x:Name="grpWebsite" VerticalAlignment="Top" HorizontalAlignment="Left"  Margin="73,245,0,0" Grid.ColumnSpan="2" Height="51" Width="170" BorderBrush="{x:Null}" BorderThickness="0">
        <ScrollViewer x:Name="pnScrollWebsite" VerticalScrollBarVisibility="Auto"  HorizontalScrollBarVisibility="Disabled" Margin="0,0,0,-6">
            <StackPanel x:Name="pnWebsite" Orientation="Vertical" Grid.ColumnSpan="2" HorizontalAlignment="Left" Margin="1,2,0,0" VerticalAlignment="Top" IsEnabled="True">

            </StackPanel>
        </ScrollViewer>
    </GroupBox>

按钮后面的代码是:

private void btWebsite_Click(object sender, RoutedEventArgs e)
{
    var newTextBox = new TextBox();
    newTextBox.Text = "type the website address...";
    newTextBox.Foreground = Brushes.Gray;
    newTextBox.Width = 150;
    newTextBox.Name = "txtWebsite" + iWebsites;
    pnWebsite.Children.Add(newTextBox);
    pnWebsite.RegisterName(newTextBox.Name, newTextBox);

    iWebsites++;
}

在我的 ViewModel 中,我有:

public List<string> Websites
{
    get { return _websites; }
    set
    {
        if (value != _websites)
        {
            _websites = value;
            OnPropertyChanged("Websites");
        }
    }
}

我正在努力了解如何将网站文本框放入视图模型列表中。谢谢你的帮助

【问题讨论】:

  • 更好地使用ItemsControl 绑定到网站集合:&lt;ItemsControl ItemsSource="{Binding Path=Websites}"/&gt;。将网站设为ObservableCollection&lt;string&gt;,将字符串添加到集合中 - 它将显示在视图中
  • 您可能想通过WPF chat room 来。我们专注于应用于 WPF 的 MVVM。注意:你需要至少 15 名代表才能在那里交谈。
  • 谢谢,但我只有 11 个代表,所以不能在那里发帖
  • 我将查找 ItemsControl。谢谢你。我对这一切都很陌生,所以我需要找到一些实现示例:)
  • 你现在应该很好了。

标签: c# wpf mvvm data-binding


【解决方案1】:

从代码隐藏中删除您的事件处理程序:btWebsite_Click。

像这样修改你的 xaml:

<Button x:Name="btWebsite" Grid.ColumnSpan="2" Width="50" Height="50" Command="{Binding AddNewStringCommand}" Margin="23,245,259,202">
        <StackPanel x:Name="pnWebsiteButton" Orientation="Horizontal">
            <Image x:Name="imgWebsite" Source= "Images/webIcon.jpg" Stretch="Fill"  HorizontalAlignment="Left" VerticalAlignment="Top"/>
        </StackPanel>
</Button>
<GroupBox x:Name="grpWebsite" VerticalAlignment="Top" HorizontalAlignment="Left"  Margin="73,245,0,0" Grid.ColumnSpan="2" Height="51" Width="170" BorderBrush="{x:Null}" BorderThickness="0">
    <ScrollViewer x:Name="pnScrollWebsite" VerticalScrollBarVisibility="Auto"  HorizontalScrollBarVisibility="Disabled" Margin="0,0,0,-6">
        <StackPanel x:Name="pnWebsite" Orientation="Vertical" Grid.ColumnSpan="2" HorizontalAlignment="Left" Margin="1,2,0,0" VerticalAlignment="Top" IsEnabled="True">

            <ItemsControl ItemsSource="{Binding Websites}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <TextBox Text="{Binding Mode=TwoWay}"/>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>

        </StackPanel>
    </ScrollViewer>
</GroupBox>

您还需要修改您的 ViewModel:

public ObservableCollection<string> Websites { get; set; }

public ICommand AddNewStringCommand => new RelayCommand(AddNewString);

private void AddNewString()
{
    Websites.Add(string.Empty);
}

您可以使用ICommand 的任何实现来代替RelayCommand。例如,我使用 MVVMLight。

如您所见,主要区别:

  • 没有处理 Click 事件,而是有一个命令绑定 按钮。
  • 不是从后面的代码生成新控件,而是有一个 每次我们有一个新的时创建一个 ItemsControl 集合中的元素。
  • 新 TextBox 的 Text 属性绑定到新元素。

更新:

我犯了一个错误,ObservableCollection 不能直接使用 TextBox。

看来你还需要一些东西:

public class Website
{
    public string Name { get; set; }
}

像这样修改 ViewModel:

public ObservableCollection<Website> Websites { get; set; } = new ObservableCollection<Website>();

public ICommand AddNewStringCommand => new RelayCommand(AddNewString);

private void AddNewString()
{
    Websites.Add(new Website {Name = "new website"});
}

ItemsTemplate 是这样的:

<ItemsControl.ItemTemplate>
    <DataTemplate>
        <StackPanel >
            <TextBox Text="{Binding Name, Mode=TwoWay}"/>
        </StackPanel>
    </DataTemplate>
</ItemsControl.ItemTemplate>

【讨论】:

  • 谢谢,看起来不错。我已经实施了您的建议,但现在页面上没有显示新的文本框。
  • @TheresaFerguson 我添加了一些更新,因为我进行了测试,但它无法正常工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多