mardi 12 août 2014

c# - affichage de plus qu'un simple texte dans un ListView ? -Débordement de pile


I have a UI for managing teams which are composed of a name and two colors (among other things). I'd like for the ListView (on the left) to display the name, a swatch of the primary color, and a swatch of the secondary color for each line. I'm very new at WPF and databinding, and I'm not really sure where to start.


Current:


current


Goal:


Goal


Relevant code:


Team.cs


public class Team : INotifyPropertyChanged
{
private string _name;
private Color _color;
private Color _secondaryColor;

public string name { ... }
public Color color { ... }
public Color secondaryColor { ... }

public event PropertyChangedEventHandler PropertyChanged;

public Team(string name, Color color, Color secondaryColor)
{
_name = name;
_color = color;
_secondaryColor = secondaryColor;
}

protected void OnPropertyChanged(string propertyName) { ... }
}

SettingsWindow.xaml.cs


public SettingsWindow()
{
teams = TeamManager.Instance().teamList;
this.DataContext = this.teams;
if (!Application.Current.Resources.Contains("selectedTeam"))
Application.Current.Resources.Add("selectedTeam", selectedTeam);
InitializeComponent();
}

SettingsWindow.xaml


<ListView ItemsSource="{Binding}" Grid.Column="0" Grid.Row="1" DisplayMemberPath="name"
SelectionChanged="ListTeamSelected" SelectionMode="Single">

<!-- I'm guessing it'll go somewhere in the ItemContainerStyle,
but I'm not sure if that's correct or how to do it -->

<!--<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Foreground" Value="{Binding color}" />
</Style>
</ListView.ItemContainerStyle>-->
</ListView>

TeamManager.cs


public class TeamList : ObservableCollection<Team>
{
public TeamList() : base() { }
}

As always, any help is greatly appreciated!




You can use ItemTemplate:


<ListView ItemsSource="{Binding}" Grid.Column="0" Grid.Row="1"
SelectionChanged="ListTeamSelected" SelectionMode="Single">
<ListView.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding name}" Margin="5"/>
<Rectangle Fill="{Binding color, Converter="{StaticResource colorFixer}}" Width="25" Margin="5"/>
<Rectangle Fill="{Binding secondaryColor, Converter="{StaticResource colorFixer}}" Width="25" Margin="5"/>
</WrapPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

but you can't use Color as Fill (or Background for a Border) you have to convert it to a Brush first. in order to do so you can create a converter as follows:


public class ColorFixer : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return new SolidColorBrush((Color)value);
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

finally add it to your xaml's resources:


<conv:ColorFixer x:Key="colorFixer"/>

make sure you have included the namespace for the converter class:


<Window    
...
xmlns:conv="clr-namespace:WpfApplication1"

Edit


you can avoid using a converter and simply use the following code instead:


<ListView ItemsSource="{Binding}" Grid.Column="0" Grid.Row="1"
SelectionChanged="ListTeamSelected" SelectionMode="Single">
<ListView.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding name}" Margin="5"/>
<Rectangle Width="25" Margin="5">
<Rectangle.Fill>
<SolidColorBrush Color="{Binding color}"/>
</Rectangle.Fill>
</Rectangle>
<Rectangle Width="25" Margin="5">
<Rectangle.Fill>
<SolidColorBrush Color="{Binding secondaryColor}"/>
</Rectangle.Fill>
</Rectangle>
</WrapPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>



Have a look into the ItemTemplate property. You can specify a DataTemplate and write xaml within here to specify the layout. You can then do something like this, as the DataContext for each ListViewItem will map to what you specify as the ItemSource.



<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Name="{Binding name}"/>
<Rectangle Fill="{Binding color}"/>
<!-- etc -->
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>


Edit: Note the removal of the DisplayMemberPath property.



I have a UI for managing teams which are composed of a name and two colors (among other things). I'd like for the ListView (on the left) to display the name, a swatch of the primary color, and a swatch of the secondary color for each line. I'm very new at WPF and databinding, and I'm not really sure where to start.


Current:


current


Goal:


Goal


Relevant code:


Team.cs


public class Team : INotifyPropertyChanged
{
private string _name;
private Color _color;
private Color _secondaryColor;

public string name { ... }
public Color color { ... }
public Color secondaryColor { ... }

public event PropertyChangedEventHandler PropertyChanged;

public Team(string name, Color color, Color secondaryColor)
{
_name = name;
_color = color;
_secondaryColor = secondaryColor;
}

protected void OnPropertyChanged(string propertyName) { ... }
}

SettingsWindow.xaml.cs


public SettingsWindow()
{
teams = TeamManager.Instance().teamList;
this.DataContext = this.teams;
if (!Application.Current.Resources.Contains("selectedTeam"))
Application.Current.Resources.Add("selectedTeam", selectedTeam);
InitializeComponent();
}

SettingsWindow.xaml


<ListView ItemsSource="{Binding}" Grid.Column="0" Grid.Row="1" DisplayMemberPath="name"
SelectionChanged="ListTeamSelected" SelectionMode="Single">

<!-- I'm guessing it'll go somewhere in the ItemContainerStyle,
but I'm not sure if that's correct or how to do it -->

<!--<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Foreground" Value="{Binding color}" />
</Style>
</ListView.ItemContainerStyle>-->
</ListView>

TeamManager.cs


public class TeamList : ObservableCollection<Team>
{
public TeamList() : base() { }
}

As always, any help is greatly appreciated!



You can use ItemTemplate:


<ListView ItemsSource="{Binding}" Grid.Column="0" Grid.Row="1"
SelectionChanged="ListTeamSelected" SelectionMode="Single">
<ListView.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding name}" Margin="5"/>
<Rectangle Fill="{Binding color, Converter="{StaticResource colorFixer}}" Width="25" Margin="5"/>
<Rectangle Fill="{Binding secondaryColor, Converter="{StaticResource colorFixer}}" Width="25" Margin="5"/>
</WrapPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

but you can't use Color as Fill (or Background for a Border) you have to convert it to a Brush first. in order to do so you can create a converter as follows:


public class ColorFixer : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return new SolidColorBrush((Color)value);
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

finally add it to your xaml's resources:


<conv:ColorFixer x:Key="colorFixer"/>

make sure you have included the namespace for the converter class:


<Window    
...
xmlns:conv="clr-namespace:WpfApplication1"

Edit


you can avoid using a converter and simply use the following code instead:


<ListView ItemsSource="{Binding}" Grid.Column="0" Grid.Row="1"
SelectionChanged="ListTeamSelected" SelectionMode="Single">
<ListView.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding name}" Margin="5"/>
<Rectangle Width="25" Margin="5">
<Rectangle.Fill>
<SolidColorBrush Color="{Binding color}"/>
</Rectangle.Fill>
</Rectangle>
<Rectangle Width="25" Margin="5">
<Rectangle.Fill>
<SolidColorBrush Color="{Binding secondaryColor}"/>
</Rectangle.Fill>
</Rectangle>
</WrapPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>


Have a look into the ItemTemplate property. You can specify a DataTemplate and write xaml within here to specify the layout. You can then do something like this, as the DataContext for each ListViewItem will map to what you specify as the ItemSource.



<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Name="{Binding name}"/>
<Rectangle Fill="{Binding color}"/>
<!-- etc -->
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>


Edit: Note the removal of the DisplayMemberPath property.


0 commentaires:

Enregistrer un commentaire