Привязка списка к ComboBox в WPF - PullRequest
0 голосов
/ 13 мая 2018

Я пытаюсь создать пользовательский интерфейс с WPF, используя MVVM, но у меня возникли некоторые проблемы.Я хочу иметь DataGrid с двумя столбцами.Первый столбец будет меткой, а второй столбец будет иметь ComboBox.Столбец метки всегда отображается, но в ComboBox ничего не отображается.Я не думаю, что связываю это должным образом, но я не уверен, как это исправить.

Я создал класс со свойствами, которые я хочу отображать в DataGrid.Метка будет свойством Parameter, и у меня есть свойство списка, называемое Revisions для ComboBox.

class RevisionMapModel
{
    private string _parameter;
    public string Parameter
    {
        get { return _parameter; }
    }

    private List<string> _revisions;
    public List<string> Revisions
    {
        get { return _revisions; }

    }

    private string _selection;
    public string Selection
    {
        get { return _selection; }
        set { _selection = value; }
    }


    public RevisionMapModel(string parameter, List<string> revisions)
    {

        // set the parameter name and the list of revisions
        _parameter = parameter;
        _revisions = revisions;
        _selection = "";


        // add a default revision
        _revisions.Add("None");

        // attempt to find which revision matches with this parameter
        FullRevisionMatch(_parameter, _revisions);

        // if a full match isn't found, then try again
        if (_selection == "None")
        {
            PartialRevisionMatch(_parameter, _revisions);
        }
    }
}

Вот класс ViewModel, который служит DataContext.DataGrid привязан к свойству RevisionMapModels, которое является списком предыдущего класса.

class RevisionMapViewModel
{

    private string _label;
    public string Label
    {
        get { return _label; }

    }

    private List<RevisionMapModel> _revisionMapModels;
    public List<RevisionMapModel> RevisionMapModels
    {
        get { return _revisionMapModels; }
    }


    public RevisionMapViewModel(List<Definition> parameters, List<Revision> revisions, string label)
    {

        // instantiate the list
        _revisionMapModels = new List<RevisionMapModel>();
        _label = label;



        // convert the parameters and revisions to strings
        List<string> revisionDescriptions = revisions.Select(r => r.Description).ToList();
        List<string> parameterNames = parameters.Select(p => p.Name).ToList();


        // create classes for each parameter
        List<string> reservedRevisions = new List<string>();
        for (int i=0; i< parameterNames.Count; i++)
        {
            RevisionMapModel model = new RevisionMapModel(parameterNames[i], revisionDescriptions);


            // check to ensure this parameter is not mapped to a revision that is already selected
            if (reservedRevisions.Contains(model.Selection))
            {
                // change the selection to none if it's already used
                model.Selection = "None";
            }
            else
            {
                reservedRevisions.Add(model.Selection);
            }


            // add it to the list
            _revisionMapModels.Add(model);

        }


    }

}

Это мой XAML ниже.Я предполагаю, что у него проблемы с привязкой к свойству Revisions, потому что это список.Я пробовал несколько вещей, но, кажется, ничего не дает этого показать.

<Window x:Class="SheetRevisions.RevisionMapView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:SheetRevisions"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800" MinWidth="500" MinHeight="500" Width="500">
    <Grid>
        <DataGrid Margin="20,40,20,45" MinWidth="50" MinHeight="47" ItemsSource="{Binding RevisionMapModels}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Parameter Name" Binding="{Binding Parameter}" Width="Auto"/>
                <DataGridComboBoxColumn Header="Revision Description" ItemsSource="{Binding Revisions}" Width="*" />        
            </DataGrid.Columns>
        </DataGrid>
        <Label Content="{Binding Label}" HorizontalAlignment="Left" Height="25" Margin="20,10,0,0" VerticalAlignment="Top" Width="412"/>
        <Button Content="Cancel" HorizontalAlignment="Right" Margin="0,0,20,10" VerticalAlignment="Bottom" Width="75" IsCancel="True"/>
        <Button Content="OK" HorizontalAlignment="Right" Margin="0,0,110,10" VerticalAlignment="Bottom" Width="75" IsDefault="True"/>

    </Grid>
</Window>

Я действительно новичок в WPF, поэтому любая помощь приветствуется.

Ответы [ 2 ]

0 голосов
/ 13 мая 2018

В дополнение к приведенным выше комментариям о реализации INotifyPropertyChanged мне также нужно было изменить свой XAML, чтобы использовать DataGridTemplateColumn вместо DataGridComboBoxColumn. Это связано с тем, что список не является действительным источником, как я узнал из этого поста:

https://social.msdn.microsoft.com/Forums/en-US/e14be49f-1c03-420e-8a15-ca98e7eedaa2/how-to-bind-net-4-datagridcomboboxcolumn-to-a-collection-within-a-collection?forum=wpf

Рабочий XAML:

<Window x:Class="SheetRevisions.RevisionMapView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:SheetRevisions"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800" MinWidth="500" MinHeight="500" Width="500">

    <Grid>
        <DataGrid Margin="20,40,20,45" MinWidth="50" MinHeight="47" ItemsSource="{Binding RevisionMapModels}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Parameter Name" Binding="{Binding Parameter}" Width="*" IsReadOnly="True"/>


                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox ItemsSource="{Binding Revisions}" SelectedItem="{Binding Selection}" Width="Auto"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>


            </DataGrid.Columns>
        </DataGrid>
        <Label Content="{Binding Label}" HorizontalAlignment="Left" Height="25" Margin="20,10,0,0" VerticalAlignment="Top" Width="412"/>
        <Button Content="Cancel" HorizontalAlignment="Right" Margin="0,0,20,10" VerticalAlignment="Bottom" Width="75" IsCancel="True"/>
        <Button Content="OK" HorizontalAlignment="Right" Margin="0,0,110,10" VerticalAlignment="Bottom" Width="75" IsDefault="True"/>

    </Grid>
</Window>

Пересмотренная модель:

public class RevisionMapModel : INotifyPropertyChanged
{

    #region fields

    private Logger _logger = LogUtils.LogFactory.GetCurrentClassLogger();

    private string _parameter;
    public string Parameter
    {
        get { return _parameter; }
        set { }
    }

    private List<string> _revisions;
    public List<string> Revisions
    {
        get { return _revisions; }


    }

    private string _selection;
    public string Selection
    {
        get { return _selection; }
        set
        {
            _selection = value;
            OnPropertyRaised("Selection");
        }

    }

    public event PropertyChangedEventHandler PropertyChanged;


    public RevisionMapModel(string parameter, List<string> revisions)
    {

        // set the parameter name and the list of revisions
        _parameter = parameter;
        _revisions = revisions;
        _selection = "";



        // add a default revision
        _revisions.Add("None");

        // attempt to find which revision matches with this parameter
        FullRevisionMatch(_parameter, _revisions);

        // if a full match isn't found, then try again
        if (_selection == "None")
        {
            PartialRevisionMatch(_parameter, _revisions);
        }
    }

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

}
0 голосов
/ 13 мая 2018

Как уже упоминалось здесь, вам необходимо реализовать INotifyPropertyChanged в вашей ViewModel.Что-то вроде

RevisionMapViewModel : INotifyPropertyChanged

//...your code here

public event PropertyChangedEventHandler PropertyChanged;

protected void NotifyPropertyChanged(String info) {
    if (PropertyChanged != null) {
        PropertyChanged(this, new PropertyChangedEventArgs(info));
    }
}

Тогда RevisionMapModel должен быть публичным классом, как мне кажется.Кроме того, если вы работаете в Visual Studio, некоторые подсказки о ваших неправильных привязках можно увидеть в окне «Вывод».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...