1

我正在我的 WPF 应用程序中动态生成标签、按钮和文本框。好吧,我成功地动态创建了它们,但我面临着一个主要问题。

xml:

<ListBox x:Name="myViewChannelList" HorizontalAlignment="Stretch" Height="Auto" ItemsSource="{Binding}" Margin="0" VerticalAlignment="Stretch" Width="Auto">
            <ListBox.ItemTemplate>
                <DataTemplate >
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="170" />
                            <ColumnDefinition />                                
                        </Grid.ColumnDefinitions>

                        <Label Grid.Column="0" Content="{Binding Path=ChanelName}" Margin="50,20,0,0"></Label>

                        <Grid Grid.Column="1">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition />
                                <ColumnDefinition />
                            </Grid.ColumnDefinitions>
                            <TextBox Grid.Column="0" Text="{Binding Path=VoltageText}" Height="25" Width="50" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" />
                            <Button Grid.Column="1" Content="Set" Height="25" Command="{Binding ElementName=myViewChannelList, Path=DataContext.SetCommand}" Width="50" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" ></Button>
                        </Grid>                            
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
</ListBox>

型号类:

private string _ChanelName = "";
public String ChanelName
    {
        get
        {
            return _ChanelName;
        }

        set
        {
            if (value != _ChanelName)
            {
                _ChanelName = value;
                OnPropertyChanged("ChanelName");                    
            }
        }            
    }

    // Constructor
    public VoltageModel(string ChanelName)
    {
        this.ChanelName = ChanelName;            
    }

    public override string ToString()
    {
        return _ChanelName;
    }

视图模型类:

class ChannelList : ObservableCollection<VoltageModel>, INotifyPropertyChanged
{
   private string _VoltageText;
    public string VoltageText
    {
        get { return _VoltageText; }
        set
        {
            _VoltageText = value;
            OnPropertyChanged("VoltageText");
        }
    }       

    // Method gets called when Set Button Is Clicked
    public void SetCommandExecuted()
    {
        string val = VoltageText;
    }

    //Notify Property Changed members are present
}

Xaml.cs 类:

ChannelList myChanels = new ChannelList();                        

public VoltageView() // Constructor
{
     InitializeComponent();            
     myChanels.Add(new VoltageModel("VDD__Main"));
     myChanels.Add(new VoltageModel("VDD__IO__AUD"));
     myChanels.Add(new VoltageModel("VDD__CODEC__AUD"));                      
     myViewChannelList.DataContext = myChanels;            
}  

当我运行应用程序时,这给了我 3 个标签(内容如上)、3 个文本框和 3 个按钮。

现在,当我在文本框中输入值时,当我在 SetCommandExecuted() 中放置断点时,单击按钮时会显示 null。最重要的是,我单击的 4 个按钮中的任何一个都会生成事件。我希望第一个文本框和第一个按钮同步(绑定),第二个文本框和第二个按钮同步等等。基本上,每个控件必须与连续的另一个控件同步。它不应该影响其他行。是否可以???

4

2 回答 2

3

这是您问题的解决方案。作为一般做法,您希望在后面的代码中避免所有逻辑、构建数据等。所有业务逻辑都应该在视图模型中,这将使单元测试更容易。

这是视图

.xaml

<StackPanel>
    <ListBox HorizontalAlignment="Stretch" 
             Height="Auto" 
             ItemsSource="{Binding VoltageCollection}"
             VerticalAlignment="Stretch" 
             Width="Auto">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <Label Width="100" 
                           Content="{Binding ChannelName}" />
                    <TextBox Width="100" 
                             Text="{Binding VoltageText}" />
                    <Button Margin="10,0,0,0" 
                            Content="Set" 
                            Command="{Binding VoltageCommand}" 
                            CommandParameter="{Binding VoltageText}" />
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</StackPanel>

这是后面的代码

.xaml.cs

    private ChannelListViewModel m_voltageViewModel;
    public MainWindow()
    {
        InitializeComponent();

        m_voltageViewModel = new ChannelListViewModel();
        m_voltageViewModel.Initialize();

        DataContext = m_voltageViewModel;
    }

这是模型:电压模型

public class VoltageModel : INotifyPropertyChanged
{
    public string ChannelName { get; set; }

    private string m_voltageText;
    public string VoltageText
    {
        get { return m_voltageText; }
        set 
        { 
            m_voltageText = value;
            OnPropertyChanged("VoltageText");
        }
    }

    public ICommand VoltageCommand { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

这是 ViewModel:ChannelListViewModel

public class ChannelListViewModel
{
    private ICommand m_voltageCommand;
    public ChannelListViewModel()
    {
        m_voltageCommand = new DelegateCommand(x => SetCommandExecute(x));
    }

    public void Initialize()
    {
        VoltageCollection = new ObservableCollection<VoltageModel> { new VoltageModel() { ChannelName = "VDD__Main", VoltageText = String.Empty, VoltageCommand = m_voltageCommand },
                                                                     new VoltageModel() { ChannelName = "VDD__IO__AUD", VoltageText = String.Empty, VoltageCommand = m_voltageCommand },
                                                                     new VoltageModel() { ChannelName = "VDD__CODEC__AUD", VoltageText = String.Empty, VoltageCommand = m_voltageCommand }};
    }

    public ObservableCollection<VoltageModel> VoltageCollection { get; set; }

    public void SetCommandExecute(object voltageText)
    {
        Debug.WriteLine(voltageText);
    }
}

最后是简单的 DelegateCommand 类DelegateCommand

public class DelegateCommand : ICommand
{
    Action<object> m_executeDelegate;

    public DelegateCommand(Action<object> executeDelegate)
    {
        m_executeDelegate = executeDelegate;
    }

    public void Execute(object parameter)
    {
        m_executeDelegate(parameter);
    }

    public bool CanExecute(object parameter) { return true; }
    public event EventHandler CanExecuteChanged;
}

截图运行

于 2012-10-11T05:04:15.623 回答
0

我没有深入了解哪里出了问题,因为我认识到 2 件事通常是非常错误的,它们可能是您的意外行为的问题。

第一个:您的 DataTemplate 将您的控件放在另一个之上。

使固定 :

     <DataTemplate >
            <Grid>
                <Grid.ColumnDefinitions>
                     <ColumnDefinition />
                     <ColumnDefinition />
                     <ColumnDefinition />
                </Grid.ColumnDefinitions>

                <Label Grid.Column="0" Content="{Binding Path=ChanelName}" />
                <TextBox Grid.Column="1" Text="{Binding Path=VoltageText}" />
                <Button Grid.Column="2" Command="{Binding ElementName=myViewChannelList, Path=DataContext.SetCommand}" />
            </Grid>
        </DataTemplate>

第二个:您的属性是在 PropertyChanged 事件发生后设置的,因此在您下次输入值之前不会更新它们。

使固定 :

private T _property;
public T Property
{
    get { return _property; }
    set
    {
        _property = value;
        OnPropertyChanged("Property");
    }
}           

如果您仍有问题,请进行这些修复并编辑您的帖子,在我的回答下发表评论。

于 2012-10-10T06:17:58.277 回答