Binding in code question - c#

I am using the same window that serves two purposes. Inside my window, i have a listview that I want to bind to DIFFERENT objects based on the purpose.
Actually its just a window that takes in import files.
So initially I had this.
<ListView Grid.Row="1" Name="_lvValues"
DataContext="{Binding ElementName=_listbox,Path=SelectedItem}"
ItemsSource="{Binding Path=DataTable(from selectedItemObject)}">
For the other purpose I had to do this
<ListView Grid.Row="1" Name="_lvValues"
DataContext="{Binding ElementName=ClassName,Path=Object}"
ItemsSource="{Binding Path=DataTable(from Object)}">
I want to do this in an if/else statement during the initialization of the window (constructor). So...
if (windowType == Type1)
// SetBinding to using listbox
else
// SetBinding to using Object
I tried this After initialize component
binding = new Binding("DataTable");
binding.Source = new Binding("ListBox.SelectedItem");
_lvValues.SetBinding(ListView.ItemsSourceProperty, binding);
But obviously it didn't work and i have no idea how to proceed.
Reason I need this is, the first window type there is a LIST of file, where second window type only has ONE file so it would not be right to show a listbox with just one file.
Thanks and Regards,
Kev

If your Xaml is an accurate description of your binding you just need to translate it into the two resulting bindings; should be something like this for the first case:
Binding contextBinding = new Binding("SelectedItem");
contextBinding.Source = _listbox;
_lvValues.SetBinding(ListView.DataContextProperty, contextBinding);
Binding itemsBinding = new Binding("DataTable");
_lvValues.SetBinding(ListView.ItemsSourceProperty, itemsBinding);
and the second case is probably this:
Binding contextBinding = new Binding("Object");
contextBinding.Source = ClassName;
_lvValues.SetBinding(ListView.DataContextProperty, contextBinding);
Binding itemsBinding = new Binding("DataTable");
_lvValues.SetBinding(ListView.ItemsSourceProperty, itemsBinding);
(Since the ItemsSource-Binding is always the same and just depends on the DataContext you could refactor it to be outside of the if-clause or in the Xaml altogether i think)

Related

C# WPF non-mvvm page converter

I'm code some app with different pages in one window. First of all i use MVVM pattern, but later i understand what using this pattern for so small application is not necessary.
But im MVVM version i use page converter for xaml binding.
Let me show what i mean:
MainWindow.xaml
<Frame
Name="MainFrame"
Content="{Binding ApplicationViewModel.CurrentPage, Source={x:Static local:ViewModelLocator.Instance}, Converter={conv:ApplicationPageValueConverter}}"
NavigationUIVisibility="Hidden" />
In ValueConverter i use switch with enum parameter, and return new Page(),
like:
case ApplicationPage.HelloPage:
return new HelloPage();
So i regreet MVVM pattern.
But now then i use this container, it doesnt work at all.
I use backend file for pages and window. In window backend file i use property with OnPropertyChanged. But when page changes, converter dont work.
Ok, i found answer.
I forgot specify DataContext of backend file.
public MainWindow()
{
InitializeComponent();
Thread.CurrentThread.CurrentCulture = new CultureInfo("ru-RU");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("ru-RU");
DataContext = this;
}
So, that's it! =)

WPF control properties set in 'code behind', after that binding is ignored

I'm really new in WPF. I tried to set a default value for a control-property in code and want to overwrite the property by data binding, when the datacontext (VM) is available. But the databinding is not working in this case.
Example:
code behind:
public partial class MyViewControl : UserControl
{
public MyViewControl()
{
InitializeComponent();
// it works if I remove this line
panelControl.Visibility = Visibility.Hidden;
}
}
xaml usercontrol:
<DockPanel Name="panelControl" Visibility="{Binding
MyViewModelProperty_IsVisible_ConvertedToVisibility}">
xaml mainwindow:
<my:MyViewControl DataContext="{Binding ElementName=lbListBox,
Path=SelectedItem}"/>
Actually the FallbackValue parameter works for this scenario, but I want to know the technical reason, why the control property cannot be bound after it was set by code?
Xaml is processed during InitializeComponent(), so this is what is happening:
InitializeComponent(); // binding is set
panelControl.Visibility = Visibility.Hidden; // binding is removed (value is set)
You can restore binding
InitializeComponent();
panelControl.Visibility = Visibility.Hidden;
BindingOperations.SetBinding(panelControl, Control.VisibilityProperty,
new Binding()
{
Path = new PropertyPath(nameof(ViewModel.MyViewModelProperty_IsVisible_ConvertedToVisibility)),
Source = viewModelInstance, // this.DataContext ?
});
And it will work after. But it's not really clear why do you want to overwrite binding in first place.
A simple way to prevent a binding being cleared when changing bound property value in code, is to use TwoWay binding mode:
<DockPanel Name="panelControl"
Visibility="{Binding MyViewModelProperty_IsVisible_ConvertedToVisibility,
Mode=TwoWay}">
I found this out the hard way, of course, lol.
Actually, using TwoWay mode does make sense if you have a reason for modifying a control's property directly (as opposed to modifying the bound property) - you would then want the bound property to reflect the change too.
By the way, instead of binding to a property of type Visibility it is better to use bind to a boolean and use a converter like BooleanToVisibilityConverter as it decouples ViewModel from View even better:
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Window.Resources>
...
<DockPanel Name="panelControl"
Visibility="{Binding MyViewModelProperty_IsVisible,
Converter={StaticResource BooleanToVisibilityConverter},
Mode=TwoWay}">
Yeah, I know this is an old question and has an accepted answer but I found no other answer offering this solution directly.

How to Bind ComboBox Selected Item property in code behind of UserControl in a Windows 8.1 store app

The below XAML binding works fine, but I can't get the binding to work when creating it in the code behind of the user control rather than in XMAL like below.
SelectedItem="{Binding ElementName=LabelledComboBoxControl, Path=SelectedItem, Mode=OneWay}"
Any help would be much appreciated.
Well, the equivalent binding in code behind would be something like this:
element.SetBinding(Selector.SelectedItemProperty, new Binding() {
Path = new PropertyPath("SelectedItem"),
Mode = BindingMode.OneWay,
Source = this.LabelledComboBoxControl;
});
Here, element is the UI element whose SelectedItem property is binded in the code that you shared. I assume you have this.LabelledComboBoxControl which is the element that you're binding to. Also, you may change Selector.SelectedItemProperty to ActualElementType.SelectedItemProperty but I guess whatever you are using is just extending Selector, so it would be the same.

How to debug databinding

I'm new to data-binding and I am having a hard-time setting it up for my WPF application:
I have a class Test which implements INotifyPropertyChanged and a property Text.
When I do this in the code-behind:
Binding b = new Binding("Text");
b.Source = Test;
label1.SetBinding(ContentProperty, b);
everything works great.
When I do the same thing in XAML:
Content="{Binding Source=Window.Test, Path=Text}"
The label content does not update.
I would like to avoid having to do this in the code-behind, what am I doing wrong?
The easiest solution is to give a name to the Window in XAML (e.g. root) and use ElementName to define the binding source:
Content="{Binding ElementName=root, Path=Test.Text}"
For simplicity, set the window DataContext to your Test instance:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new Test
{
Text = "Hello, World!"
};
}
}
Then declare databinding in XAML:
Content="{Binding Path=Text}"
what am I doing wrong?
You are making unfounded assumptions about how something ought to work about which you do not have much of a clue. You are dealing with two fundamentally different languages here and just because you want WPF to interpret Window.Test as a reference to some specific window you had in mind does not make it so.
XAML is fundamentally string-based, for the most part strings are converted to primitive types like ints and doubles, e.g. when you set the height of a control you pass a string to a property of type double. The XAML parser knows via reflection that the property is of type double and tries to convert the string (using a default value converter if no other has been specified). Now what do you think happens if a property is of type object? What is the parser to do? Well, it is not going to do anything as a string is already an object.
Guess what type Binding.Source has and what the source object of your binding will be when you write Window.Test...

Binding WPF combo box to specific dictionary instance

I am new to WPF and I am trying to get databinding to work with a combo box. I have a class I created called FolderList that basically wraps around a FileSystemWatcher instance. It has a property called Folders that returns a dictionary of the folder names and their full paths.
Then for the class for my WPF window it has contains an instance of FolderList called FolderWatcher that is configured in the constructor. I would like to databind a combobox to the dictionary in that specific instance of FolderList.
I've found examples where there are static instances of data objects or where they are created through XAML but I can't figure out how to bind to a specific instance.
I am not picking if this is done in XAML or C#. I've basically gotten this far with the ObjectDataProvider.
<Window.Resources>
<ObjectDataProvider x:Key="ProjectNames"
ObjectType="{x:Type local:FolderList}"
/>
</Window.Resources>
And here is the combo box I want to data bind. This doesn't produce any errors but it also isn't populated. I know enough to know I am missing something major in the ObjectDataProvider but I just don't know what it is.
<ComboBox Name="ProjectCombo" MinWidth="100" ItemsSource="{Binding Source={StaticResource ProjectNames}, Path=Folders}" />
You don't need a the ObjectDataProvider here. Just set ItemsSource of your ComboBox directly in the Window's contructor, where you initialize your instance of FolderList:
public MyWindow()
{
InitializeComponent();
FolderWatcher = new FolderList(...);
ProjectCombo.ItemsSource = FolderWatcher.Folders;
}
Another option would be to set the instance of FolderList as DataContext of your window and then use binding to set ItemsSource of theComboBox`:
public MyWindow()
{
InitializeComponent();
FolderWatcher = new FolderList(...);
DataContext = FolderWatcher;
}
<ComboBox Name="ProjectCombo" MinWidth="100" ItemsSource="{Binding Folders}" />
I suggest you look into MVVM pattern. If you designed your application according to that pattern, you would have a View Model instance as DataContext of your view and that View Model would expose a property you could bind to.

Categories

Resources