I have a simple wpf app, that I want to try to use ItemsSource binding from xaml. When I click the button. it should be updated also in the UI, but it doesn't.
Why doesn't it work?
Xaml code:
<Window x:Class="SendRawEthernetPacketsGUI.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<ComboBox HorizontalAlignment="Left" Margin="76,65,0,0" VerticalAlignment="Top" Width="120" ItemsSource="{Binding test}"/>
<Button Content="Button" HorizontalAlignment="Left" Margin="90,171,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
</Grid>
C# code:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace SendRawEthernetPacketsGUI
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public ObservableCollection<string> test = new ObservableCollection<string>();
public Window1()
{
InitializeComponent();
DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
test.Add("fdfddf");
}
}
}
It feels kinda stupid to even ask this, but even looking in google didn't help me. So can you?
Your binding never worked in the first place. You can only bind to properties not fields.
Try this instead:
public ObservableCollection<string> test { get; set; }
public Window1()
{
Test = new ObservableCollection<string>();
}
Or if you want some tricky C# 6 magic:
public ObservableCollection<string> test => new ObservableCollection<string>();
This is a function bodied-member and compiles to a read-only property that is initialized to the new ObservableCollection
Caveats/Design Errors:
Note that in both cases you aren't using INotifyPropertyChanged, so wholesale assignments to the collection won't be picked up by the UI. You should also be using PascalCase for your public properties, and using a proper view model instead of binding to the code-behind.
Related
I have made a list that is a property amnd then given that list values and this is still not working to place in a listview as a itemsource i have no idea how to fix this and get results is there anyone that can show me what im doing wrong here? i am placing the data context in the MainWindow
XAML
<Window x:Class="CRM.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CRM"
mc:Ignorable="d"
Title="MainWindow" Height="1080" Width="1920">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="0*"/>
</Grid.ColumnDefinitions>
<ListView ItemsSource="{Binding tickets}" Margin="0,10,1075,0" MaxWidth="990"/>
</Grid>
</Window>
MainViewModel:
using API.Objects;
using API.ViewModels;
using System;
using System.Collections.Generic;
using System.Text;
namespace API.ViewModels
{
public class MainViewModel : BaseViewModel
{
int Counter{ get; set; }
List<TicketO> tickets { get; set;}
public MainViewModel()
{
TicketO ticket = new TicketO("Jens", "Svensson", "jenson1234#live.se", "0767942768", "This is working but my box is not", 500);
tickets.Add(ticket);
}
}
}
MainWindow
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using API.ViewModels;
namespace CRM
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainViewModel();
}
}
}
Make tickets public, DataContext = this; is missing, refer below link.
How can I bind a List as ItemSource to ListView in XAML?
In MODEL, there is a list<string>.
In VIEWMODEL, there is IList<MODEL>.
And I want to binding at ComboBox in VIEW
But when i binding ItemsSource to MODEL list, VIEW look to VIEWMODEL.
So binding alway fail.
How can solve this problem?
class Model
{
private IList<string> _comboItems;
public IList<string> ComboItems
{
get => _comboItems;
set => SetProperty(ref _comboItems, value);
}
}
class ViewModel
{
private IList<Model> _modelList;
public IList<Model> ModelList
{
get => _modelList;
set => SetProperty(ref _modelList, value);
}
}
VIEW
<....>
<GridView>
<GridViewComboBoxColumn ItemsSource="{binding ModelList}"/>
</GridView>
I guess that you have a datagrid and you want to populate a column by combobox with strings come from ComboItems. If this is your goal: you have to keep in mind the following points.
you have to set the DataContext pointing your
Your ViewModel has, at least implements INotifyPropertyChanged, however if you have to do a large use of mvvm I suggest you to use one mvvm framework like MVVM Light or Caliburn Micro there are many however
the ItemsSource of your datagrid have to be able to notify changes to your view, it has to be something like an ObservableCollection or a BindingList
If you want to change the comboboxitems at runtime add or remove or items also ComboBoxItems has to be a BindingList ... it is not very good to have bindinglist in a model.
well based on what I say you could do in this way I use traditional WPF your code seems to be UWP
MainWindow.xaml:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx /2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
<Grid>
<DataGrid ItemsSource="{Binding ModelList}">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" />
<DataGridTemplateColumn Header="MyComboColumn" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource ="{Binding ComboItems}" BorderThickness="0" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
namespace WpfApplication2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
ViewModel vm = new ViewModel();
DataContext = vm;
vm.ModelList = new BindingList<Model>();
Model md = new Model();
md.ComboItems = new List<string>();
md.ComboItems.Add("string1");
md.ComboItems.Add("string2");
md.ComboItems.Add("string3");
vm.ModelList.Add(md);
md = new Model();
md.ComboItems = new List<string>();
md.ComboItems.Add("string4");
md.ComboItems.Add("string5");
md.ComboItems.Add("string6");
vm.ModelList.Add(md);
}
}
}
ViewModel
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
namespace WpfApplication2
{
public class ViewModel : INotifyPropertyChanged
{
private BindingList<Model> _modelList;
public BindingList<Model> ModelList
{
get { return _modelList; }
set { _modelList = value;
NotifyPropertyChanged("ModelList");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
}
Model
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WpfApplication2
{
public class Model
{
private IList<string> _comboItems;
public IList<string> ComboItems
{
get { return _comboItems; }
set { _comboItems = value; }
}
}
}
i'm trying to learn WPF and on top of that the MVVM style of doing things.
I have a simple practice app in which i would like to display codes in a combo box.
My Code
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace SteamCodes
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private ObservableCollection<Codes> codes;
public MainWindow()
{
InitializeComponent();
codes = new ObservableCollection<Codes>()
{
new Codes() {CodeID = "1", Code="CODETEXT"}
};
steamCode.ItemsSource = codes.ToString();
}
}
public class Codes
{
public string CodeID { get; set; }
public string Code { get; set; }
}
}
My XAML
<Window x:Class="SteamCodes.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SteamCodes"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ComboBox x:Name="steamCode" ItemsSource="{Binding Source = Codes}" HorizontalAlignment="Left" Height="43" Margin="122,37,0,0" VerticalAlignment="Top" Width="259"/>
</Grid>
</Window>
At the moment my Combo box is Pulling through as each option in the ComboBox is a letter from the line 'System.Collections.Objectmodel.ObservableCollection`1[SteamCodes.Codes]'
Everyone of those letters is a different drop down option in the combo box.
Any Ideas where i have gone wrong.
Your ComboBox ItemSource must be a collection of items, not a string:
steamCode.ItemsSource = codes;
You also have to specify which property of your item must be considered as value to be shown in combobox by setting DisplayMemberPath property:
steamCode.DisplayMemberPath = "Code";
To specify which property of bound objects will be used as actual selected value you have to use SelectedValuePath property:
steamCode.SelectedValuePath = "CodeID";
The MVVM approach is this:
public class ViewModel
{
public ObservableCollection<Codes> Codes { get; }
= new ObservableCollection<Codes>();
}
The MainWindow constructor:
public MainWindow()
{
InitializeComponent();
var viewModel = new ViewModel();
viewModel.Codes.Add(new Codes { CodeID = "1", Code = "CODETEXT" });
DataContext = viewModel;
}
The XAML:
<ComboBox ItemsSource="{Binding Codes}" DisplayMemberPath="Code" .../>
I'm currently playing with wpf for the first time and I'm coming into some issues. I cannot figure out how to reference the wpf label element. I changed my label name to "label1" and try referencing it in my c# code, but alas no result just errors such as.
xaml
<Controls:MetroWindow x:Class="Rustomatic.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Rustomatic"
Height="350"
Width="525" >
<Grid>
<Label x:Name="label1" Content="Label" HorizontalAlignment="Left" Margin="229,128,0,0" VerticalAlignment="Top"/>
</Grid>
<Window.InputBindings>
<KeyBinding Gesture="F5" Command="{Binding Hit}" />
</Window.InputBindings>
c#
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using MahApps.Metro.Controls;
namespace Rustomatic
{
public partial class MainWindow : MetroWindow
{
label1.content = "hi";
}
public class Hit
{
}
}
Please take it lightly I was an intermediate at C# once but I haven't used it in a couple of years.
You give names to elements in xaml by using x:Name, this will cause them to be publicly named in designer generated cs-file (it is made out of xaml) and you can access them as you did it in past in winforms.
This code doesn't makes any sense:
public partial class MainWindow : MetroWindow
{
label1.content = "hi";
}
You can't access label1 like this. You have to do it in the property getter/setter or method:
public partial class MainWindow : MetroWindow
{
public void SomeMethod()
{
label1.Content = "hi";
}
}
Also, don't remove constructor InitializeComponent() call, otherwise your window will not get initialized. This is important (unless you add partial class in addition to partial class made for you when you add new window to project):
public MainWindow()
{
InitializeComponent();
}
I've got a weird error when trying to create a simple sample using the latest version of Reactive UI.
The window opens and I get a system error
Couldn't find view for 'Hi Bob!'
note: 'Hi Bob!' is the first item in the list.
What am I missing here?
Thanks.
versions
ReactiveUI 6.5.0
Splat 1.6.2
.net 4.5
Sample code
xaml
<Window x:Class="ListBind.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel Orientation="Horizontal">
<ListBox Name="ListBox1"></ListBox>
</StackPanel>
</Grid>
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using ReactiveUI;
namespace ListBind
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, IViewFor<ViewModel>
{
public MainWindow()
{
ViewModel = new ViewModel();
DataContext = ViewModel;
InitializeComponent();
this.OneWayBind(ViewModel, m => m.Items, v => v.ListBox1.ItemsSource);
}
public ViewModel ViewModel
{
get { return (ViewModel)GetValue(ViewModelProperty); }
set { SetValue(ViewModelProperty, value); }
}
public static readonly DependencyProperty ViewModelProperty =
DependencyProperty.Register("ViewModel", typeof(ViewModel), typeof(MainWindow), new PropertyMetadata(null));
object IViewFor.ViewModel
{
get { return ViewModel; }
set { ViewModel = (ViewModel)value; }
}
}
public class ViewModel : ReactiveObject
{
public ReactiveList<string> Items = new ReactiveList<string>(new[] { "Hi Bob!", "Two", "Three" });
}
}
The thing with ReactiveUI when you bind to things like a ListBox using the OneWayBind method, is that it will try to automatically apply a custom template for the data based upon the views it finds with Splat.Locator.Resolve. In your case, it is trying to find and build a view based on the "Hi Bob!" ViewModel, which obviously doesn't exist.
What you should do is force it to use a custom data template so that it doesn't try to apply a non-existing template. With a template below, it shouldn't try and resolve a view for you, but rather stick the "Hi Bob!" value into the TextBlock.
<ListBox x:Name="ListBox1">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
There is a slim chance that ReactiveUI will still ignore that (I cannot verify right now), so if that is the case, replace the OneWayBind binding with the traditional ItemSource={Binding Data}.