【问题标题】:Two way binding not working correctly两种方式绑定无法正常工作
【发布时间】:2012-01-11 22:41:14
【问题描述】:

我正在使用 WPF MVVM 模式。我的视图中有 2 个 ListBox 和一个 DataGrid。我正在使用 EntityFramework 从 SQL Server 获取数据。我的 ViewModel 看起来像这样

    private Types _type;
    private Users _user;
    private ObjectResult<APP> _dataContext;

    public IEnumerable<Types> Categories
    {
        get;
        private set;
    }

    public IEnumerable<Users> SystemNames
    {
        get;
        private set;
    }

    public Types SelectedType
    {
        get
        {
            return _type;
        }
        set
        {
            _type = value;
            RaisePropertyChanged("SelectedType");
        }
    }       

    public Users SelectedUser
    {
        get
        {
            return _user;
        }
        set
        {
            _user = value;
            RaisePropertyChanged("SelectedUser");
        }
    }

    public ObjectResult<APP> DContext
    {
        get
        {
            return _dataContext;
        }
        set
        {
            _dataContext = value;
            RaisePropertyChanged("DContext");
        }
    }

    public ObjectResult<APP> GetDataContext()
    {
        AppLogEntities context = new AppLogEntities();
        return context.GetAppLog(SelectedUser.User, SelectedType.Type);
    }

    public DetailsViewModel()
    {
        Categories = new List<Types>
        {
            new Types{Type = "All"},
            new Types{Type = "Information"},
            new Types{Type = "Warning"},
            new Types{Type = "Error"}
        };

        SystemNames = new List<Users>
        {
            new Users{User = "All"},
            new Users{User = "SYS_01"},
            new Users{User = "SYS_02"}
        };

        SelectedType = new Types();
        SelectedUser = new Users();

        DContext = GetDataContext();
    }`

我的观点是这样的

<Window x:Class="SingleAppLogMVVM.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vm="clr-namespace:SingleAppLogMVVM"
    Title="MainWindow" Height="800" Width="1000">
<Window.DataContext >
    <vm:DetailsViewModel />
</Window.DataContext>
<Grid>
    <ListBox Height="200" HorizontalAlignment="Left" Margin="50,50,0,0" Name="fTypeListBox" VerticalAlignment="Top" Width="125" SelectionMode="Single" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Categories}" SelectedItem="{Binding SelectedType, Mode=TwoWay}" >
        <ListBox.ItemTemplate >
            <DataTemplate >
                <DockPanel Width="120" LastChildFill="True" >
                    <TextBlock Text="{Binding Type, Mode=TwoWay}" Width="110" Margin="5" />
                </DockPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    <ListBox Height="Auto" HorizontalAlignment="Left" Margin="50,275,0,50" Name="fUserListBox" VerticalAlignment="Stretch" Width="125" SelectionMode="Single" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding SystemNames}" SelectedItem="{Binding SelectedUser, Mode=TwoWay}"  >
        <ListBox.ItemTemplate >
            <DataTemplate >
                <DockPanel Width="120" LastChildFill="True" >
                    <TextBlock Text="{Binding User, Mode=TwoWay}" Width="110" Margin="5" />
                </DockPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    <DataGrid AutoGenerateColumns="False" Height="350" HorizontalAlignment="Stretch" Margin="225,50,50,0" IsReadOnly="True" Width="Auto"
              VerticalAlignment="Top" CanUserReorderColumns="False" CanUserResizeColumns="False" Name="fDGrid"  VirtualizingStackPanel.IsVirtualizing="True"
              CanUserResizeRows="False" IsManipulationEnabled="True" RowHeight="35" SelectionMode="Single" VirtualizingStackPanel.VirtualizationMode="Recycling"
              ItemsSource="{Binding DContext, Mode=OneWay}">
        <DataGrid.Columns>
            <DataGridTextColumn Header="ID" Binding="{Binding Path=ID}" Width="5*" />
            <DataGridTextColumn Header="IID" Binding="{Binding Path=IID}" Width="5*" />
            <DataGridTextColumn Header="INSTANCEID" Binding="{Binding Path=INSTANCEID}" Width="10*" />
            <DataGridTextColumn Header="TYPE" Binding="{Binding Path=TYPE}" Width="10*" />
            <DataGridTextColumn Header="SOURCE" Binding="{Binding Path=SOURCE}" Width="10*" />
            <DataGridTextColumn Header="TIME" Binding="{Binding Path=TIME}" Width="10*" />
            <DataGridTextColumn Header="SNAME" Binding="{Binding Path=SNAME}" Width="10*" />
            <DataGridTextColumn Header="MESSAGE" Binding="{Binding Path=MESSAGE}" Width="15*" />
            <DataGridTextColumn Header="ACTIONS" Binding="{Binding Path=ACTIONS}" Width="15*" />
            <DataGridTextColumn Header="CLEARED ON" Binding="{Binding Path=CLEAREDON}" Width="10*" />
        </DataGrid.Columns>
    </DataGrid>        
</Grid>

我能够填充我的 LisBoxes。如果在我的 ViewModel 代码中手动设置插件值,我也可以填充我的 DataGrid

 public ObjectResult<APP> GetDataContext()
    {
        AppLogEntities context = new AppLogEntities();
        return context.GetAppLog(SelectedUser.User, SelectedType.Type);
    }

根据我从 ListBoxes 中的选择,我不明白为什么它不起作用。请帮帮我。

【问题讨论】:

  • 注意:您不应该公开访问 dataContex。而且不异步调用查询是个坏主意——它会阻塞应用程序并带来很多麻烦。
  • 我将 _dataContext 声明为私有。我还需要做什么?如果我手动将值放入 GetDataContext 方法中,我可以填充我的 DataGrid。

标签: wpf mvvm datagrid


【解决方案1】:

需要进行一些小的更改才能获得您想要的结果

public Types SelectedType
{
    get
    {
        return _type;
    }
    set
    {
        _type = value;
        RaisePropertyChanged("SelectedType");
        DContext = GetDataContext(); //refresh the data
    }
}       

public Users SelectedUser
{
    get
    {
        return _user;
    }
    set
    {
        _user = value;
        RaisePropertyChanged("SelectedUser");
        DContext = GetDataContext(); //refresh the data
    }
}


public DetailsViewModel()
{
    Categories = new List<Types>
    {
        new Types{Type = "All"},
        new Types{Type = "Information"},
        new Types{Type = "Warning"},
        new Types{Type = "Error"}
    };

    SystemNames = new List<Users>
    {
        new Users{User = "All"},
        new Users{User = "SYS_01"},
        new Users{User = "SYS_02"}
    };

    _type = new Types();  //use the field rather than the property so GetDatacontenxt doesnt get called multiple times
    _user = new Users();
    DContext = GetDataContext();
}

【讨论】:

    【解决方案2】:

    每次在视图模型中更改 SelectedUser 和 SelectedType 属性时,您都需要手动调用 GetDataContext()。属性设置器是执行此操作的好方法 - 尽管如果 GetDataContext() 是一个长时间运行的操作,那么您应该异步执行它,这样 UI 在结果加载时不会冻结。

    【讨论】:

    • 你能解释一下吗。我是 WPF MVVM 的初学者。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-18
    • 1970-01-01
    • 1970-01-01
    • 2011-10-07
    • 2021-06-25
    • 2021-11-08
    • 2017-02-09
    相关资源
    最近更新 更多