动态文本框绑定到列表

时间:2017-02-07 14:05:00

标签: c# wpf mvvm data-binding

我对MVVM很新,而且我遇到了数据绑定问题。我的视图页面上有一个按钮,可以动态创建文本框,但是我无法看到如何将这些文本框绑定到ViewModel中的List。

在我看来,我有:

InvalidOperationException

按钮背后的代码是:

$(document).bind('scroll',function(e){
    $('div').each(function(){
        if ($(this).offset().top < window.pageYOffset + 10 && $(this).offset().top + $(this).height() > window.pageYOffset + 10){
            window.location.hash = $(this).attr('id');

            if($(this).attr('id') == "first"){
                $("#navlist a").css('color', 'white');
                $("#nav1").css('color', 'red');
            }else if($(this).attr('id') == "second"){
                $("#navlist a").css('color', 'white');
                $("#nav2").css('color', 'red');
            }else if($(this).attr('id') == "third"){
                $("#navlist a").css('color', 'white');
                $("#nav3").css('color', 'red');
            }

        }
    });
});

在我的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>

我很难看到如何将网站文本框放入viewmodel列表中。谢谢你的帮助

1 个答案:

答案 0 :(得分: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);
}

您可以使用RelayCommand的任何实现,而不是ICommand。我使用的例如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>