Reputation: 55
I am new to C# and WPF and still learning the ropes. I am currently trying use a ListBox to display some predefined items in a list. I am using an ObservableCollection to hold those items and I am binding that collection to that ListBox. I am also allowing the user to add new items to the list or update selected ones in addition to deleting them. For each item in that list I want to display a DELETE button beside it. However each button should only be visible for the items that have been added by the user and not any of the predefined items.
I am currently able to display the DELETE button for each item in the list. Therefore my question is, is it possible to set the the property of the DELETE button for each item in the list to be visible only for the items that were newly added to it and have no DELETE buttons showing for the predefined(default) items? If so, how would I go about doing that? (That is what I am struggling to figure out.)
Should I post my code?
Thanks
Here is the viewmode which has the list and the controls to add new items to the list.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ListBox x:Name="DrinksListBox" HorizontalAlignment="Center" Height="325" Width="275" Margin="0,0,0,0" VerticalAlignment="Center" Grid.Column="0">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="0,2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Type}" Width="80" Margin="0,0,10,0" Grid.Column="0"/>
<TextBlock Text="{Binding Name}" Width="80" Margin="0,0,10,0" Grid.Column="1" HorizontalAlignment="Left"/>
<Button x:Name="DrinkDeleteButton" Content="Delete" Click="CmdDeleteDrink_Clicked" HorizontalAlignment="Right" Grid.Column="2"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBox x:Name="DrinkNameTextBox" Grid.Column="1" HorizontalAlignment="Left" Height="45" Margin="0,0,0,100" TextWrapping="Wrap" Text="Enter Drink Name" VerticalAlignment="Center" Width="240" FontSize="20" VerticalContentAlignment="Center"/>
<ComboBox x:Name="DrinkTypeComboBox" Grid.Column="1" HorizontalAlignment="Left" Margin="0,47,0,0" VerticalAlignment="Top" Width="240" Height="45" ItemsSource="{Binding Drinks, Mode=OneWay}" DisplayMemberPath="Type" FontSize="20"/>
<Button x:Name="AddDrinkButton" Content="Add Drink" Grid.Column="1" HorizontalAlignment="Right" Margin="0,0,10,100" VerticalAlignment="Center" Width="100" Height="45" Click="CmdAddDrink_Clicked"/>
</Grid>
Here is my code-behind. I have a inner class for the drink property and the main class that sets up the list to be used.
public partial class MainWindow : Window
{
public ObservableCollection<Drinks> Drinks { get; private set; }
public MainWindow()
{
InitializeComponent();
Drinks = new ObservableCollection<Drinks>();
Drinks.Add(new Drinks("Soda", "Pepsi"));
Drinks.Add(new Drinks("Tea", "Lemon"));
Drinks.Add(new Drinks("Caffinated", "Coffee"));
Drinks.Add(new Drinks("Other", "Water"));
DrinksListBox.ItemsSource = Drinks;
DrinkTypeComboBox.ItemsSource = Drinks;
}
private void CmdDeleteDrink_Clicked(object sender, RoutedEventArgs e)
{
Button cmd = (Button)sender;
if (cmd.DataContext is Drinks deleteDrink)
{
Drinks.Remove(deleteDrink);
}
}
private void CmdAddDrink_Clicked(object sender, RoutedEventArgs e)
{
string typeSelection = ((Drinks)DrinkTypeComboBox.SelectedItem).Type;
Drinks.Add(new Drinks(typeSelection, DrinkNameTextBox.Text));
}
}
Drink class has the type of drink and a name for it. public class Drinks { private string type; private string name;
public Drinks(string type, string name)
{
this.type = type;
this.name = name;
}
public string Type
{
get { return type; }
set
{
if (type != value)
{
type = value;
}
}
}
public string Name
{
get { return name; }
set
{
if (name != value)
{
name = value;
}
}
}
}
Upvotes: 1
Views: 55
Reputation: 17668
Let's say you have your item:
public class Drinks
{
//your properties, simplified for clarity
public string Name {get;set;}
public string Type {get;set;}
//hey, a new one!
public bool IsUserDefined {get;set;}
}
Then, when the user adds one:
private void CmdAddDrink_Clicked(object sender, RoutedEventArgs e)
{
string typeSelection = ((Drinks)DrinkTypeComboBox.SelectedItem).Type;
Drinks.Add(new Drinks(typeSelection, DrinkNameTextBox.Text)
{
IsUserDefined = true
});
}
disclaimer: from the top of my head; normally that means syntax errors; removed some parts for clarity.
<!-- In your resources section of the XAML -->
<BooleanToVisibilityConverter x:Key="BoolToVis" />
<ListBox x:Name="DrinksListBox" ItemSource="{Binding Drinks}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Type}"/>
<TextBlock Text="{Binding Name}"/>
<Button x:Name="DrinkDeleteButton"
Visibility="{Binding Path=IsUserDefined,
Converter={StaticResource BoolToVis}}"/>
<!-- note: left out some attributes for clarity -->
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
That should do the trick.
Btw, you seem to be mixing some typical MVVM style coding and code-behind coding. It's worth to say that you might benefit by using a ViewModel in your code.
Upvotes: 0