所以我有一个FlowListView,我想为FlowListView的每个单元格放置与默认图像不同的图像,但是我想通过if条件放置它,而if条件需要按钮的Text属性。我尝试在ViewModel和xaml.cs文件中执行此操作,但是在ViewModel中,我不知道如何获取按钮的Text属性,在xaml.cs文件中,我不知道如何在构造函数中执行此操作。
Xaml代码:
<flv:FlowListView FlowColumnCount="3" SeparatorVisibility="Default" HasUnevenRows="true" FlowColumnExpand="ProportionalLast"
FlowItemTappedCommand="{Binding ItemTappedCommand}" FlowLastTappedItem="{Binding LastTappedItem}"
FlowItemsSource="{Binding MyCategories}" >
<flv:FlowListView.FlowColumnTemplate>
<DataTemplate>
<Button Text="{Binding Name}"
Image="carne.png"
Command="{Binding IdCatalogs}"
CommandParameter="{Binding Id}"
TextColor="White"
Clicked="ButtonSelected"
ContentLayout="Top"
BackgroundColor="#40000000"
BorderColor="#FFFFFF"
BorderWidth="2"
CornerRadius="6">
</Button>
</DataTemplate>
</flv:FlowListView.FlowColumnTemplate>
</flv:FlowListView>
Xaml.cs文件代码:
public partial class CategoriesMenuDetail : ContentPage
{
public Dictionary<int, Btn> buttons { get; set; }
public CategoriesMenuDetail()
{
InitializeComponent();
buttons = new Dictionary<int, Btn>();
}
public void ButtonSelected(object sender, EventArgs e)
{
var button = (Button)sender;
if (!buttons.ContainsKey(button.GetHashCode()))
{
buttons.Add(button.GetHashCode(), new Btn(button));
}
bool state = buttons[button.GetHashCode()].Toogle();
if (button.Text == "Carnes")
{
var image = (state) ? "carneslc.png" : "carne.png";
button.Image = image;
}
if (button.Text == "Peixes")
{
var image = (state) ? "peixeslc.png" : "peixe.png";
button.Image = image;
}
if (button.Text == "Entradas")
{
var image = (state) ? "entradaslc.png" : "entrada.png";
button.Image = image;
}
var bgColor = (state) ? Color.FromHex("#26047AD5") : Color.FromHex("#40000000");
var borderColor = (state) ? Color.FromHex("#FF8A00") : Color.FromHex("#FFFFFF");
button.BackgroundColor = bgColor;
button.BorderColor = borderColor;
}
}
public class Btn
{
private Button _button { get; set; }
private bool isToogle = false;
public Btn(Button button)
{
_button = button;
}
public bool Toogle()
{
isToogle = !isToogle;
return isToogle;
}
}
ViewModel代码:
private RestaurantsClient restaurantsClient { get; set; }
private ObservableCollection<CategoryDetail> _myCategories;
public ObservableCollection<CategoryDetail> MyCategories
{
set
{
_myCategories = value;
NotifyPropertyChanged(nameof(MyCategories));
}
get
{
return _myCategories;
}
}
public RestaurantsReaderViewModel()
{
restaurantsClient = (App.Current as App).restaurantsClient;
var restaurantsNames = restaurantsClient.GetCategoriesAsync(2).Result;
MyCategories = new ObservableCollection<CategoryDetail>(restaurantsNames.Categories);
}
CategoryDetailModel:
public partial class CategoryDetail
{
[Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.Always)]
public int Id { get; set; }
[Newtonsoft.Json.JsonProperty("name", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public string Name { get; set; }
public string ToJson()
{
return Newtonsoft.Json.JsonConvert.SerializeObject(this);
}
public static CategoryDetail FromJson(string data)
{
return Newtonsoft.Json.JsonConvert.DeserializeObject<CategoryDetail>(data);
}
}
答案 0 :(得分:1)
您可以通过两种不同的方式解决此问题:
Image
属性。对于ValueConveter方法,您需要实现IValueConveter
接口,它看起来可能像这样:
public class CategoryImageValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var name = (string)value;
switch (name)
{
case "Entradas":
return "entradas.png";
case "Carnes":
return "carnes.png";
case "Peixes":
return "peixes.png";
// add more here
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
然后,您需要告诉Xamarin.Forms在哪里寻找此ValueConverter。因此,在页面上添加:
<ContentPage.Resources>
<ResourceDictionary>
<local:CategoryImageValueConverter x:Key="categoryImage" />
</ResourceDictionary>
</ContentPage.Resources>
现在,您可以将Image
属性的绑定更改为:
Image="{Binding Name, Converter{StaticResource categoryImage}}"
对于将其直接放入CategoryDetail类的其他解决方案,您只需创建一个新属性,并使用正确的图像名称填充这些项目并绑定该属性。对于本示例,我们将其称为ImageName
:
Image="{Binding ImageName}"
在CategoryDetail中看起来像这样:
private string _imageName;
public string ImageName
{
get => _imageName;
set
{
_imageName = value;
}
}
如果您的CategoryDetail类实现了InotifyPropertyChanged,请记住,如果稍后设置图像名称,也会触发PropertyChanged事件。
答案 1 :(得分:0)
您将Command按钮绑定到IdCatalog,可能是一个数字值,它应该是ICommand属性,并且您的VM应该如下所示:
public ICommand MyButtonCommand => new Command( (param) =>{ ... });
//Param is CommandParameter value, you should cast before use it
如果要使用UI的事件,首先必须从VM绑定Image属性,并将其设置为notificable属性。
如果将图像更改为代码,则不会通知UI值已更改。
已编辑:
您的结构良好的代码应该是这样
public partial class CategoriesMenuDetail : ContentPage
{
public CategoriesMenuDetailViewModel ViewModel { get; set; }
public CategoriesMenuDetail()
{
ViewModel = new CategoriesMenuDetailViewModel();
InitializeComponent();
BindingContext = Viewmodel;
}
}
public class CategoriesMenuDetailViewModel
{
public List<CategoryDetail>MyCategories { get; set; } // if you don't add new items not need observable collection
public ICommand ButtonClickedCommand => new Command((cParameter)=> ButtonclickedCommandExecute((CategoryDetail)cParameter)
private void ButtonclickedCommandExecute(CategoryDetail myParam)
{
//Here goes you image's logic
if (myParam.Name == "Carnes")
myParam.ImageName = Image.FromFile("");
}
}
public class CategoryDetail : ObservableObject
{
public int Id { get; set; }
private string _name;
public string Name { get =>_name; set=>SetProperty(ref _name, value); }
private string _imageName;
public string ImageName { get=>_imageName; set=>SetProperty(ref _imageName, value); }
}
public class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetProperty<T>(ref T backingStore, T value, [CallerMemberName] string propertyName = "", Action onChanged = null)
{
if (EqualityComparer<T>.Default.Equals(backingStore, value))
return false;
backingStore = value;
onChanged?.Invoke();
OnPropertyChanged(propertyName);
return true;
}
}
和XAML
<flv:FlowListView FlowColumnCount = "3" SeparatorVisibility="Default" HasUnevenRows="true" FlowColumnExpand="ProportionalLast"
FlowItemTappedCommand="{Binding ItemTappedCommand}" FlowLastTappedItem="{Binding LastTappedItem}"
FlowItemsSource="{Binding MyCategories}" >
<flv:FlowListView.FlowColumnTemplate>
<DataTemplate>
<Button Text = "{Binding Name}"
Image="{Binding ImageName}"
Command="{Binding ButtonClickedCommand}"
CommandParameter="{Binding .}"
TextColor="White"
Clicked="ButtonSelected"
ContentLayout="Top"
BackgroundColor="#40000000"
BorderColor="#FFFFFF"
BorderWidth="2"
CornerRadius="6">
</Button>
</DataTemplate>
</flv:FlowListView.FlowColumnTemplate>
</flv:FlowListView>