I am trying to bind the result from WCF service to devexpress lookupedit.
this is the property I created
<!-- language: c# -->
public class BindingModel
{
private static List < VW_ClientProcess> _clientProcess= new List< VW_ClientProcess>();
public List< VW_ClientProcess> clientProcess
{
get
{
return _clientProcess;
}
set
{
_clientProcess = value;
OnPropertyChanged("clientProcess");
}
}
}
}
In WPFApp.xaml.cs
BindingModel bind=new BindingModel();
bind.clientProcess = e.Result.GetClientProcessesResult.ToList< VW_ClientProcess>();
this is my xaml code(WPFApp.xaml)
<dxlc:LayoutGroup>
<dxlc:LayoutGroup.DataContext>
<ViewModel:BindingModel />
</dxlc:LayoutGroup.DataContext>
<dxlc:LayoutItem x:Name="liClientProcess"
Width="auto"
VerticalAlignment="Bottom"
Label="Client Process"
LabelPosition="Top">
<dxg:LookUpEdit x:Name="lueClientProcess"
AutoPopulateColumns="True"
DisplayMember="ClientFullName"
ItemsSource="{Binding clientProcess}"
ValueMember="ProcessID" />
</dxlc:LayoutItem>
</dxlc:LayoutGroup>
The problem is when I set ItemSource in xaml, only column names are displaying but the data fields are empty.
but If I set ItemSource through c# code like this
BindingModel bind = new BindingModel();
lueClientProcess.ItemsSource = bind.clientProcess;
lookupedit edit is getting populated. I am new to WPF. I don't know what I am doing wrong here.
It looks like the problem is you are creating duplicate instances of BindingModel. So here in the XAML creates one instance, and assigns it to the view's DataContext:
<dxlc:LayoutGroup.DataContext>
<ViewModel:BindingModel />
</dxlc:LayoutGroup.DataContext>
But then this doesn't use the existing instance, but creates a new one that isn't attached anywhere to the UI:
BindingModel bind=new BindingModel();
bind.clientProcess = e.Result.GetClientProcessesResult.ToList< VW_ClientProcess>();
So I guess what you'd want, instead of the above:
var bind = (BindingModel)DataContext;
bind.clientProcess = e.Result.GetClientProcessesResult.ToList< VW_ClientProcess>();
Related
I am attempting to bind a list to a combobox. I want to display this list of options within the Combobox itself. (Later to allow the user to select an item 'SelectedItem', I'll cross that bridge when I get there)
MyCode.cs
// List of values for 'Type' dropdown
private static readonly List<string> MarkerTypeList = new List<string>(new string[]
{
"Analog",
"Digital"
});
// Binding for viewing list in window
public List<string> TypeOptions
{
get { return MarkerTypeList; }
}
MyCode.xaml
<ComboBox x:Name="myCombobox" HorizontalAlignment="Left" Margin="125,26,0,0" VerticalAlignment="Top" Width="70" Height="23" SelectedItem="" ItemsSource="{Binding TypeOptions}" />
The solution boiled down to changing this:
ItemsSource="{Binding TypeOptions}"
to this:
ItemsSource="{Binding Marker.TypeOptions}"
Thanks for the input, sorry you didnt have a whole lot to go on.
If you bind you should have your INotifyPropertyChanged interface added to your class which is the actual ViewModel for your ComboBox.
So - 1. Add the Interface to the class. 2. Create RaisePropertyChanged function. 3. Call the function through the setter of the property. This will push the updated value of the property through the binding and you will see the combobox populated.
I have ComboBox in a Datagrid that I bind in a .NET WPF application as follows:
<ComboBox x:Name="categoryValues" MinWidth="70"
IsSynchronizedWithCurrentItem="False"
SelectedValuePath="Id"
ItemsSource="{Binding Source={StaticResource categoryViewSource},
Converter={StaticResource CategoriesToCategoriesConverter}}"
SelectedItem="{Binding Category,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged,
Converter={StaticResource CategoryToCategoryConverter}}"
DisplayMemberPath="Name" SelectionChanged="categoryValues_SelectionChanged">
</ComboBox>
So each row is bound to the field Category in a different Model. The categoryViewSource is defined as follows
<CollectionViewSource x:Key="categoryViewSource" d:DesignSource="{d:DesignInstance {x:Type Models:Category}, CreateList=True}"/>
My Category Model implements INotifyPropertyChanged using PropertyChanged.Fody NuGet package. After I load the data from the database using Entity Framework, I assign the data to the CollectionViewSource as follow:
var db = new MyDbContext();
System.Windows.Data.CollectionViewSource categoryViewSource = (System.Windows.Data.CollectionViewSource)this.Resources["categoryViewSource"];
await db.Categories.LoadAsync();
categoryViewSource.Source = db.Categories.Local;
So it's bound to the Observable collection. However, once I do
var c = new Category { Name="New Category" };
db.Categories.Add(c);
my CollectionViewSource is updated (at least in the debugger), which seems logical, it's source is an ObservableCollection. But even if I do
categoryViewSource.View.Refresh();
my ComboBox ItemsSource isn't updated. I tried with IsSynchronizedWithCurrentItem="True" as seen somewhere on StackOverflow. So far it only works, if I do something like this:
categoryViewSource.Source = null;
categoryViewSource.Source = db.Categories.Local;
But then my SelectedItem property is null in all ComboBoxes and they appear empty in the Datagrid because apparently the instances of SelectedItem are different once you reassign the collection.
Does anyone have a solution. Unfortunately, I'm still really new to WPF and have no idea.
Adding a new Category to the DbSet<Category> doesn't affect the ObservableCollection<Category>. These are two different and independent in-memory collections. You will have to add the same object to both Collections.
You could create an ObservableCollection and populate this one with your entity objects when you initialize your ComboBox. And then you add any new objects to both your context and to your data-bound collection, i.e.:
public partial class MainWindow : Window
{
ObservableCollection<Category> _cats;
public MainWindow()
{
InitializeComponent();
var db = new MyDbContext();
System.Windows.Data.CollectionViewSource categoryViewSource = (System.Windows.Data.CollectionViewSource)this.Resources["categoryViewSource"];
await db.Categories.LoadAsync();
_cats = new ObservableCollection<Category>(db.Categories.Local);
categoryViewSource.Source = _cats;
//...
var c = new Category { Name = "New Category" };
db.Categories.Add(c); //add to DbSet
_cats.Add(c); //add to ObservableCollection
}
}
Ok, if I add it directly as ItemsSource, that does work. However if I add the collection through a separate Binding, it doesn't work. I need to pass the collection through the converter though. Is there a way to do it automatically?
You could set up the binding programmatically:
categoryValues.SetBinding(ComboBox.ItemsSourceProperty, new Binding(".") { Source = _cats, Converter = new CategoriesToCategoriesConverter() });
I am very new to WPF and especially to data-binding but I'm trying to populate a ListBox with elements from an external resource, and trying to also follow the MVVM pattern. As such I am trying to avoid any code in my code-behind. I've looked over dozens of other questions similar to this but I feel I am missing something stupid as I cannot get my ListBox to generate with values. I have set the DataContext and then set the Binding for the ItemsSource to the correct property.
Question
How do I simply get this code to populate my empty ListBox when the application starts up?
XAML
<TabItem Name="ServerListTab" Header="Server List">
<TabItem.DataContext>
<viewModel:ServerListViewModel />
</TabItem.DataContext>
<ListBox
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ItemsSource="{Binding ServerList, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
IsSynchronizedWithCurrentItem="True"
SelectedItem="{Binding SelectedServer}">
</ListBox>
</TabItem>
ServerList property in view model
public BindingList<string> ServerList
{
get { return _serverListModel.ServerList; }
set
{
if (ReferenceEquals(_serverListModel.ServerList, value)) return;
var aTestServers = //code hidden : gets array correctly from resource
for (var i = 0; i < aTestServers.Count; i++)
{
_serverListModel.ServerList.Add(aTestServers[i]);
}
InvokePropertyChanged("ServerList");
}
}
i want to change textblock text in page initialize event
here is my xaml
<ListBox Margin="3,60,1,10" BorderThickness="2" Grid.Row="1" Name="lstAnnouncement" Tap="lstAnnouncement_Tap" Width="476" d:LayoutOverrides="VerticalMargin">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Name="thispanel" Grid.Row="1" Orientation="Horizontal" Height="120" Width="478" >
<StackPanel.Background>
<ImageBrush ImageSource="Images/Text-ALU.png" Stretch="Fill" />
</StackPanel.Background>
<Grid HorizontalAlignment="Left" Width="30" Margin="0,0,0,2" Background="#FF0195D5" Height="118">
<TextBlock x:Name="txtDate" TextWrapping="Wrap">
</TextBlock>
</Grid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
i want to change txtDate.Text using c# in code-behind but txtdate is not accessible in code behind so how to achieve it ?
The reason you're not able to access the txtDate object is because it's contained within the DataTemplate you're using for the ListBox. This isn't an error - the DataTemplate is being applied to every single item added to your ListBox.
Given that the ListBox creates, among other controls, a Grid containing a TextBlock with the name "txtDate", for every single item added to it, what would it mean to access the txtDate object? How would your program decide which of a (functionally) infinite number of txtDates associated with an identical number of ListBoxItems you meant when you referenced txtDate?
If you wanted to be able to easily change the content of txtDate, you'd want to bind the ItemsSource of your ListBox to a property in a ViewModel. The easiest way to do this would be to have that property be an IEnumerable containing a custom model type. This way, you could update the text property of that model and call NotifyPropertyChanged on the that property, and the UI would update to reflect the new data.
Here's an example:
public class YourViewModel
{
public List<YourModel> Models { get; set; }
}
public class YourModel : INotifyPropertyChanged
{
private string yourText;
public string YourText
{
get { return yourText; }
set
{
yourText = value;
NotifyPropertyChanged("YourText");
}
}
// add INotifyPropertyChanged implementation here
}
And then you'd want to bind the ItemsSource of the ListBox to YourViewModel's Models property, and the text of your TextBox to the YourModel's YourText property. Any time you change the YourModel.YourText property, it'll automatically update on the UI. I think it's probably subject to debate whether having your model implement INotifyPropertyChanged is proper MVVM, but I find it a lot easier in these cases than forcing the ViewModel to update every single model each time a change is made on one of them.
If you're not familiar with the MVVM pattern used with WPF, this might be a good start: MVVM example.
this function will help you... This will help u find the control inside of a listbox runtime..
public FrameworkElement SearchVisualTree(DependencyObject targetElement, string elementName)
{
FrameworkElement res = null;
var count = VisualTreeHelper.GetChildrenCount(targetElement);
if (count == 0)
return res;
for (int i = 0; i < count; i++)
{
var child = VisualTreeHelper.GetChild(targetElement, i);
if ((child as FrameworkElement).Name == elementName)
{
res = child as FrameworkElement;
return res;
}
else
{
res = SearchVisualTree(child, elementName);
if (res != null)
return res;
}
}
return res;
}
Here first parameter is parent and the second parameter is the name of the element which in your case is "txtDate".. hope it works!!
I have created VM classes for the DataGrid items (Rows and Cells).
The VM class for Cell is shown below:
public class ListGridCell : INotifyPropertyChanged
{
public ListGridCell(string Name)
{
// Init properties
this.Name = Name;
this.DataValue = null;
this.DataEditor = null;
}
public string Name { get; private set; }
private object _DataValue;
public object DataValue
{
get { return _DataValue; }
set { _DataValue = value; NotifyPropertyChanged("DataValue"); }
}
private FrameworkElement _DataEditor;
public FrameworkElement DataEditor
{
get { return _DataEditor; }
set { _DataEditor = value; NotifyPropertyChanged("DataEditor"); }
}
...
}
DataGrid columns and VM is built totally dynamically from code.
I create template column (DataGridTemplateColumn) and set the CellTemplate to the followind template (illustrated through XAML):
<StackPanel>
<TextBlock Text="{Binding Path=DataValue}" />
<ContentControl Content="{Binding Path=DataEditor}" />
</StackPanel>
Everything works fine and as expected when DataGrid is initially filled and shown.
Now, If I try to SCROLL the grid the following exception occurs:
Specified element is already the logical child of another element.
Disconnect it first.
This exception has something to do with grid's row virtualization and binding Content to DataEditor inside cell template. If I turn off the row virtualization, everything works fine but grid performance becomes very bad so it is not an option.
Do you know DataGrid virtualization works behind the scenes, what happens when row is loaded/unloaded and what could be causing this error?
Are there any workarounds?
Note: I cannot use ContentTemplate binding for cell data editor in cell template (which is suggested in many places as workaround) because I MUST manually create and initialize this cell editor.
Solved.
This is obviously a bug somewhere in ContentControl when using Content binding in combination with DataGrid virtualization.
Once I switched to ContentPresenter everything works flawlessly.
Working cell template is:
<StackPanel>
<TextBlock Text="{Binding Path=DataValue}" />
<ContentPresenter Content="{Binding Path=DataEditor}" />
</StackPanel>