wpf - Wpf MVVM 中的数据绑定(bind)

标签 wpf mvvm observablecollection

我是 WPF 和 MVVM 的新手。

我尝试从 mysql 数据库中获取数据到 ObservableCollection然后将其绑定(bind)到 UI。

问题是,我在第一个 ObservableCollection 中有数据在模型层,但是当我无法将数据发送到 ViewModel 层时,没有任何东西会绑定(bind)到 UI。

class Databasecon 
{
    int i = 0;

    // First Binding for the Database
    public ObservableCollection<Operator> operators { get; private set; }

    public Databasecon()
    {
        this.operators = new ObservableCollection<Operator>(); 
    }

    public void Datacon(string conn)
    {
        MySqlConnection con = null;
        MySqlCommand com = null;
        MySqlDataReader myreader = null;
        int columnOrdinaloperatorname = -1;

        con = new MySqlConnection(conn);
        try
        {
            if (com == null)
            {
                com = new MySqlCommand("SELECT operator_name FROM operators", con);
                com.Connection.Open();

                myreader = com.ExecuteReader();
                columnOrdinaloperatorname = myreader.GetOrdinal("operator_name");

                while (myreader.Read())
                {
                    this.operators.Add(new Operator() { operatorname = myreader.GetString(columnOrdinaloperatorname).ToString() });

                    i++;
                }  
            }

            MessageBox.Show(operators.Count.ToString());
        }
        catch (MySqlException ex)
        {
            MessageBox.Show(ex.ToString());
        }
        finally
        {
            if (myreader != null)
                myreader.Close();

            if (com != null)
            {
                if (com.Connection != null)
                    com.Connection.Close();
            }
        }
    }
}

class Operator
{
    public string operatorname { get ; set; }
}

class collect : INotifyPropertyChanged
{
    private Databasecon databasecon = null;

    public event PropertyChangedEventHandler PropertyChanged;

    public ObservableCollection<Operator> operators
    {
        get
        {
            if (this.databasecon.operators != null)
            {
                return this.databasecon.operators;                   
            }
            else
            {
                return null;
            }
        }
        set
        {
            this.operators = value; RaisePropertyChanged("operators");
        }
    }

    private void RaisePropertyChanged(string propertyName)
    {
        var handler = this.PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public collect()
    { 
        this.databasecon = new Databasecon();
    }
}

Xaml 代码是:
 <Window.DataContext>
    <vm:collect/>
</Window.DataContext>
<Grid>
    <TextBlock Margin="459,51,-459,-51"><InlineUIContainer>
                <TextBlock x:Name="textBlock" TextWrapping="Wrap" Text="{Binding Path=operators}"  Width="198" FontSize="28" Height="66"/>
            </InlineUIContainer></TextBlock>
    <ListBox x:Name="listBox"  HorizontalAlignment="Left" Height="102" Margin="115,240,0,0" VerticalAlignment="Top" Width="339" ItemsSource="{Binding operators}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock >
                        <Run Text="{Binding operatorname}"></Run>
                    </TextBlock>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

谁能帮我这个?

最佳答案

您的绑定(bind)对我来说似乎很好 - 这是我为测试它们所做的:

<Window.DataContext>
    <vm:collect/>
</Window.DataContext>
<Grid>
    <Button VerticalAlignment="Top" HorizontalAlignment="Left" Command="{Binding AddThings}" Height="25" Width="Auto">Add Stuff</Button>
    <TextBlock Margin="459,51,-459,-51"><InlineUIContainer>
            <TextBlock x:Name="textBlock" TextWrapping="Wrap" Text="{Binding Path=operators}"  Width="198" FontSize="28" Height="66"/>
        </InlineUIContainer></TextBlock>
    <ListBox x:Name="listBox"  HorizontalAlignment="Left" Height="102" Margin="115,240,0,0" VerticalAlignment="Top" Width="339" ItemsSource="{Binding operators}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock >
                    <Run Text="{Binding operatorname}"></Run>
                    </TextBlock>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Grid>

C#:
class Databasecon
{
    int i = 0;

    // First Binding for the Database
    public ObservableCollection<Operator> operators { get; private set; }

    public Databasecon()
    {
        this.operators = new ObservableCollection<Operator>();
    }

    public void Datacon()
    {
            this.operators.Add(new Operator() { operatorname = "Hello world!"});
    }
}

class Operator
{
    public string operatorname { get; set; }
}

class collect : INotifyPropertyChanged
{
    private Databasecon databasecon = null;

    public event PropertyChangedEventHandler PropertyChanged;

    public ICommand AddThings { get; set; }

    public ObservableCollection<Operator> operators
    {
        get
        {
            if (this.databasecon.operators != null)
            {
                return this.databasecon.operators;
            }
            else
            {
                return null;
            }
        }
        set
        {
            this.operators = value; RaisePropertyChanged("operators");
        }
    }

    private void RaisePropertyChanged(string propertyName)
    {
        var handler = this.PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public collect()
    {
        this.databasecon = new Databasecon();
        AddThings = new SimpleCommand(() => databasecon.Datacon()); 
    }
}

public class SimpleCommand : ICommand
{
    private Action _command; 

    public SimpleCommand(Action command)
    {
        _command = command; 
    }

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

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        if (_command != null)
            _command();
    }
}

您的问题可能在于您设置数据上下文的方式。目前,您的窗口每次实例化时都会创建 View 模型的新实例,但由于您没有设置名称,我假设此实例仅由窗口使用。您可以将 vm 设为公共(public)属性并调用窗口保存的实例来填充集合:
<Window.DataContext>
    <vm:collect x:Name="Collect"/>
</Window.DataContext>


window.Collect.Datacon("[My connection string]");

或者将您打算使用的实例传递给 View 模型构造函数并将其设置在那里:
 public MainWindow(object viewModel)
    {
        DataContext = viewModel; 
        InitializeComponent();
    }

关于wpf - Wpf MVVM 中的数据绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43046609/

相关文章:

c# - 为什么 ObservableCollection 不支持批量更改?

c# - 绑定(bind)到控件模板

c# - 如何在C#wpf中获取登录用户的文档路径

c# - 为什么 GeometryDrawing 显示在带有裁剪坐标的 Canvas 上?

c# - 禁用按钮时单击按钮时的工具提示

c# - 将 TextBox 的文本绑定(bind)到 list<T> 值的总和

c# - 无法在 C# 中使用 String.Format

swift - MVVM RxSwift 将数据从主视图发送到详细 View Controller 的方法?

c# - View 模型未正确绑定(bind) C#

c# - WPF MVVM 应用程序服务层中的 ObservableCollection